嗨,我注意到如果我在 a 中包含一个头文件,.cpp那么我可以创建该头文件类的一个对象。就像如果我包括在内A.h,main.cpp那么我可以写A *a;在main.cpp. 但是,如果我在另一个头文件中包含一个头文件,然后尝试创建包含的头文件的对象,这将不起作用。像,
文件B.h:
#include "A.h"
class B
{
public:
B(){};
A *a;
};
我必须添加类的前向声明A才能使其工作。为什么?
嗨,我注意到如果我在 a 中包含一个头文件,.cpp那么我可以创建该头文件类的一个对象。就像如果我包括在内A.h,main.cpp那么我可以写A *a;在main.cpp. 但是,如果我在另一个头文件中包含一个头文件,然后尝试创建包含的头文件的对象,这将不起作用。像,
文件B.h:
#include "A.h"
class B
{
public:
B(){};
A *a;
};
我必须添加类的前向声明A才能使其工作。为什么?
以下是基础知识:
对于任何类型A,如果你声明了一个 , , , 等类型的变量A&,A*那么A**编译A***器不需要知道A变量声明处的完整定义。它只需要知道A一个类型;这就对了。所以一个前向声明就足够了:
class A; //forward declaration
class B
{
A * pA; //okay - compiler knows A is a type
A & refA;/ okay - compiler knows A is a type
};
不需要 完整的定义,因为编译器仍然可以计算sizeof(B)哪个反过来依赖于sizeof(A*)和sizeof(A&)- 这些对于编译器来说是已知的,即使它不知道 sizeof(A)。请注意,这sizeof(A*)只是该平台上的指针大小(通常 4是 32 位系统上的8字节或 64 位系统上的字节)。
对于任何类型A,如果你声明了一个类型为 , 等的变量A,A[N]那么A[M]N]编译器需要A在变量声明的地方知道类型的完整定义。在这种情况下,前向声明是不够的。
class A; //forward declaration
class B
{
A a; //error - the compiler only knows A is a type
//it doesn't know its size!
};
但这是正确的:
#include "A.h" //which defines A
class B
{
A a; //okay
};
需要完整的定义, 以便编译器可以计算,如果编译器不知道 的定义,这是不可能的。sizeof(A)A
请注意,类的定义是指“类成员、它们的类型以及类是否具有虚函数的完整规范”。如果编译器知道这些,它可以计算类的大小。
了解这些基础知识后,您可以决定是否将标头包含到其他标头中,或者仅前向声明就足够了。如果前向声明就足够了,那是您应该选择的选项。仅在需要时才包含标题。
但是,如果你在头文件中提供前向声明A,B.h那么你必须将头文件包含A.h在它的实现文件中B,B.cpp因为在的实现文件中B,你需要访问A编译器需要完整定义的成员。 A. 同样,仅当您需要访问. A:-)
对不起,我没有看到你答案的最后一段。令我困惑的是为什么我还需要前向声明。不包括头文件Ah单独提供了A类的完整定义吗?——</p>
我不知道头文件中有什么。另外,如果尽管包含了头文件,但还需要提供前向声明,则意味着头文件实现不正确。我怀疑存在循环依赖:
确保没有两个头文件相互包含。例如,如果A.h包含B.h,则B.h不得A.h直接或间接包含。
Use forward declaration and pointer-declaration to break such circular dependency. The logic is pretty much straight-forward. If you cannot include A.h in B.h, which implies you cannot declare A a in B.h (because for this, you have to include the header A.h also). So even though you cannot declare A a, you can still declare A *pA, and for this a forward declaration of A is enough. That way you break the circular dependency.
Hope that helps.