C++ 类的前向声明不';t似乎在C+中工作+;
下面的代码是在VC++6中编译的。我不明白为什么会出现编译错误C++ 类的前向声明不';t似乎在C+中工作+;,c++,header,compilation,declaration,forward-declaration,C++,Header,Compilation,Declaration,Forward Declaration,下面的代码是在VC++6中编译的。我不明白为什么会出现编译错误C2079:'b'对以下代码使用未定义的类'b' B类来源 #include "B.h" void B::SomeFunction() { } B类标题 #include "A.h" struct A; class B { public: A a; void SomeFunction(); }; #include "B.h" class B; struct A { B b;
C2079:'b'对以下代码使用未定义的类'b'
B类来源
#include "B.h"
void B::SomeFunction()
{
}
B类标题
#include "A.h"
struct A;
class B
{
public:
A a;
void SomeFunction();
};
#include "B.h"
class B;
struct A
{
B b;
};
构造一个标题
#include "A.h"
struct A;
class B
{
public:
A a;
void SomeFunction();
};
#include "B.h"
class B;
struct A
{
B b;
};
如果我将class B头更改为以下内容,则不会出现错误。但是标题声明不会在顶部
具有奇怪标题声明的B类标题
struct A;
class B
{
public:
A a;
void SomeFunction();
};
#include "A.h"
您正在尝试仅使用正向声明创建的对象。此时编译器(仅使用forward decl)无法决定对象A的大小,因此无法分配A所需的内存。因此,您无法仅使用forward decl创建对象
替换为:
A* a;
没有A的类定义的指向A的指针或引用可以正常工作 这里有两个问题向我提出 1:您编写了
Struct A
,而不是Struct A
;请注意小写字母“s”。编译器可能会考虑等价的,但我不认为它是标准的C++。
您已经定义了
a
和B
之间的循环引用。每个A对象必须包含一个B
对象,但每个B
对象必须包含一个A
对象!这是一个矛盾,永远不会按你希望的方式工作。解决这个问题的常用C++方法是使用指针或引用,用于<代码>:::b>代码>或<代码> b::a < /> >(或两者).< /p> < p>为了定义类或结构,编译器必须知道类的每个成员变量有多大。转发声明不能做到这一点。我只见过它用于指针和(不太常见的)引用
除此之外,你在这里试图做的事是做不到的。您不能让类a包含另一个类B的对象,该类B包含类a的对象。但是,您可以让类a包含指向包含类a对象的类B的指针
B.cpp
#include "B.h"
void B::SomeFunction()
{
}
B.h
#ifndef __B_h__ // idempotence - keep header from being included multiple times
#define __B_h__
#include "A.h"
class B
{
public:
A a;
void SomeFunction();
};
#endif // __B_h__
#ifndef __A_h__ // idempotence - keep header from being included multiple times
#define __A_h__
#include "B.h"
class B; // forward declaration
struct A
{
B *b; // use a pointer here, not an object
};
#endif // __A_h__
A.h
#ifndef __B_h__ // idempotence - keep header from being included multiple times
#define __B_h__
#include "A.h"
class B
{
public:
A a;
void SomeFunction();
};
#endif // __B_h__
#ifndef __A_h__ // idempotence - keep header from being included multiple times
#define __A_h__
#include "B.h"
class B; // forward declaration
struct A
{
B *b; // use a pointer here, not an object
};
#endif // __A_h__
两点。首先,确保使用某种形式的幂等性来防止每个编译单元多次包含头。第二,理解C++中,类和结构之间唯一的区别是默认可见性级别——类默认使用私有可见性,而结构默认使用公共可见性。在C++中,以下定义在功能上是等价的。
class MyClass
{
public: // classes use private visibility by default
int i;
MyClass() : i(13) { }
};
struct MyStruct
{
int i;
MyStruct() : i(13) { }
};
您还包括B.h中的A.h和A.h中的B.h。您至少应该使用预处理器宏:
#ifndef __A_H__
#define __A_H__
// A.h contents
#endif
因此,该文件不会包含多次。如果您创建了A的实例,则将创建B的实例(成员变量),这将创建A的实例(成员变量),这将创建B的实例,这将创建A的实例,依此类推。。。 编译器不应该允许这样做,因为它需要无限内存
要解决这个问题,A或B必须使用指向另一个类的引用/指针。转发声明,如
struct A;
或
将A作为不完整的类型引入,它将保持不完整,直到到达类型定义的结尾。有些事情你可以用不完整的类型做,有些事情你做不到。你可以
在代码中,您试图声明类型不完整的结构成员。这是违法的。只允许使用指针和引用。在实际代码中,定义了预处理器宏,但此处未显示以简化代码。双下划线保留给编译器。使用不同的命名约定。双下划线是为编译器保留的。使用不同的命名约定。@GMan:当编译器没有自动生成幂等标记时,我总是使用这种约定来表示幂等标记。这是特定于编译器还是在C++规范中?@ Matt,它是C++标识符的一部分,这样的标识符被保留。我个人使用“HEADER_PATH_TO_HEADER_H_INCLUDED”或“HEADER_PATH_TO_HEADER_INCLUDED”(如果没有“.H”)。你能把它们放在同一个头文件中吗?我知道这不是一个特别技术性的答案,但如果可行的话,你可以通过这样做来避免整个问题。如果你将两个类定义放在同一个头文件中,那没关系,其中一个仍然必须放在第一位,并且无法知道另一个类的大小。谢谢你的澄清,我在这方面还是个新手,希望我没有提供不好的建议,我是这样的