header 中的 C++ 语法错误使用来自另一个 header 的 class

C++ Syntax error in header using class from another header

编辑:我的 IDE 给了我一条错误消息,因为我正在进行重大重构,编译时有太多错误消息,我没有全部阅读,天真地假设我的 IDE 会知道这个问题。

问题是 FontText header 相互引用,编译器在 Text 上抛出语法错误Font header 中的标记。这是通过在 Font header 文件的顶部写入 [​​=21=] 来解决的,正如@molbdnilo 正确回答的那样。

对于我忽略编译错误的仓促行为,我深表歉意。我想将此作为信息留给未来的读者:CLion 2021.1.1 Build #CL-211.7142.21 无法检测到此错误并且 semi-incorrectly 突出显示了下面提到的表示构造函数不存在的行。无法解析 Text 构造函数,因为它循环引用了 Font header.


编译器告诉我,我声明和定义的构造函数与看似匹配的参数不匹配。我的 IDE 建议使用默认构造函数,但我有意没有定义一个。

我有以下声明并且每个成员都已实现:

class Font {
private:
  static Shader* fontShader;
  std::map<char, Character> characters;
  unsigned int VAO, VBO, EBO;
public:
  static void GLYPH_VAO_REGISTER();
  static Shader* getFontShader();
  Font(const std::string &name, int size);
  ~Font();
  Text *drawText(std::string text, float x, float y, float scale, glm::vec3 color);
};
class Text: public Renderable {
private:
  Font *font;
  const std::string &text;
public:
  Text(Font* font, const std::string &text);
};

当我尝试创建两者的新实例时,我能够创建 Font class 的实例,但不能创建 Text class 的实例:

Text* Font::drawText(std::string text, float x, float y, float scale, glm::vec3 color) {
  Text *target = new Text(this, text);
                     ^^^^ No matching constructor for initialization of 'Text'
  return target;
}

Text构造函数的定义是:

Text::Text(Font *font, const std::string &text) : Renderable(
    ("text-" + text),
    true,
    GLYPH_VERTEX_COUNT,
    nullptr,
    GLYPH_INDEX_COUNT,
    nullptr,
    true,
    &Font::GLYPH_VAO_REGISTER,
    Font::getFontShader()), font(font), text(text) {}

我的 IDE 显示 header 文件中的定义是存在的,我无法弄清楚为什么编译器似乎无法识别构造函数。非常感谢任何帮助:)

编辑:我认为重要的是要提到两个 class 声明都在不同的 header 文件中,我认为问题在于两者都无法获得定义,因为它们引用了每个其他(我排除了我现在意识到对重现错误至关重要的功能)。我得到的错误是 text.h 文件中 Font *font; 行的语法错误。在顶部添加 class Font; 似乎可以阻止语法错误,但我不确定它是否真正解决了问题。我添加了引用 Text class 的函数。我想现在我想知道为什么,即使 header 彼此包含,他们也看不到声明。

编译时的错误是 text.h(17,8): error C2143: syntax error: missing ';' before '*'(第 17 行是 Font *font; 行)和 text.h(20,7): error C2061: syntax error: identifier 'Font'(第 20 行是构造函数)。

你有问题因为 headers 相互包含,尽管如此。
请记住,#include 是一种非常原始的机制,它实际上只是在某个地方插入文件的内容。

举个简单的例子:

A.h:

#ifndef A_H
#define A_H
#include "B.h"

class A { B* b; };

#endif

B.h:

#ifndef B_H
#define B_H
#include "A.h"

class B { A* a; };

#endif

现在,在编译“A.h”时,经过预处理后看起来像这样:

class B { A* a; };
class A { B* b; };

AB 的定义中是未知的。
来自“B.h”的 #include "A.h" 变得一无所有,因为它包含在 A_H include guard 中。

同样的事情发生在“B.h”,但顺序不同。

解决方案是使用前向声明 - 因为您使用的是指针,所以您只需要 class 名称,并且您可以声明它们存在于某处。
然后你在需要它们的源文件中包含headers,一切都会由编译器解决。

A.h:

#ifndef A_H
#define A_H

class B;    
class A { B* b; };

#endif

B.h:

#ifndef B_H
#define B_H

class A;
class B { A* a; };

#endif

B.cpp:

#include "A.h"
#include "B.h"

// Use A and B freely