您好,我注意到如果我在 .cpp
中包含一个头文件,那么我可以创建该头文件类的对象。就像如果我在 main.cpp
中包含 A.h
那么我可以在 main.cpp
中编写 A *a;
。但是,如果我在另一个头文件中包含一个头文件,然后尝试创建该包含的头文件的对象,这将不起作用。喜欢,
文件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*)
只是该平台上指针的大小(通常在 32 位系统上为4
字节或在 64 位系统上为8
字节)。对于任何类型
A
,如果你声明一个A
类型的变量,A[N]
,A[M]N]
等,然后编译器需要知道类型的完整定义A
在变量声明的地方。在这种情况下,前向声明(forward declaration)不是不够的。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
的定义,这是不可能的.请注意,类的定义 表示“类成员、它们的类型以及类是否具有虚函数的完整规范”。如果编译器知道这些,它就可以计算出类的大小。
了解这些基础知识后,您可以决定是将 header 包含到其他 header 中,还是仅前向声明就足够了。如果前向声明就足够了,那就是您应该选择的选项。包含 header 仅当需要时。
但是,如果您提供 A
的前向声明在标题中 B.h
, 那么你必须包含头文件 A.h
在B
的实现文件中这是B.cpp
, 因为在 B
的实现文件中,您需要访问 A
的成员为此,编译器需要 A
的完整定义.再次重申,仅当您需要访问 A
的成员时才包括在内. :-)
Sorry I didn't see the last paragraph of your answer. What is confusing me is why do I need the forward declaration also. Doesn't including the header file A.h alone provides complete definition of class A?? –
不知道头文件里有什么。另外,如果尽管包含头文件,您还需要提供前向声明,那么它暗示头文件实现不正确。我怀疑存在循环依赖:
确保没有两个头文件相互包含。例如,如果
A.h
包括B.h
, 然后B.h
不得包括A.h
,直接或间接。使用前向声明和指针声明来打破这种循环依赖。逻辑非常简单。如果不能包含
A.h
在B.h
,这意味着您不能声明A a
在B.h
(因为为此,您还必须包含标题A.h
)。所以即使你不能声明A a
, 你仍然可以声明A *pA
,并为此前向声明A
足够。这样你就打破了循环依赖。
希望对您有所帮助。
关于c++ - 为什么一定要Forward声明一个类,在一个头文件中包含对应的头文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14413403/