header 中的 C++ 语法错误使用来自另一个 header 的 class
C++ Syntax error in header using class from another header
编辑:我的 IDE 给了我一条错误消息,因为我正在进行重大重构,编译时有太多错误消息,我没有全部阅读,天真地假设我的 IDE 会知道这个问题。
问题是 Font
和 Text
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; };
和 A
在 B
的定义中是未知的。
来自“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
编辑:我的 IDE 给了我一条错误消息,因为我正在进行重大重构,编译时有太多错误消息,我没有全部阅读,天真地假设我的 IDE 会知道这个问题。
问题是 Font
和 Text
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; };
和 A
在 B
的定义中是未知的。
来自“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