我有一个关于何时使用前向声明与包含标头的问题。我知道有很多类似的问题,但只有一件事情有点令人困惑。
我在我看到的源代码中看到了以下方式:
classA.h
#ifndef H_CLASSA
#define H_CLASSA
class classB;
class classA {
public:
classA(B* b);
};
然后在 classA.cpp :
#include "classA.h"
#include "classB.h" // dependency
classA::classA(B* b) { b->someMethod(); }
在这种情况下,我只是把#include" class.b"从一开始就在classA-header中,因为A依赖于B类并使用它。但是我不明白你为什么要先在头文件中声明classB然后在源文件中包含classB.h?
提前致谢!
答案 0 :(得分:1)
为了防止循环包括:
假设我们有以下包含路径:(每个[]是一个头文件,每个 - >包含)
[A] - > [B] - > [C]
到目前为止一切顺利。 但是如果[A]有一些类或函数从[C]中取一些对象作为参数会发生什么? 所以我们可以在[A]中包含(就像你说的那样)[C]。 不,我们可以遇到以下问题: 1)此循环包括可能导致编译器的一些错误: 首先,C包括B,B包括A,但A包括C!并且循环继续递归。 2)让我们说[A]有一个A类,[B]有一个继承自A的类B,[C]有一个继承自B的C类。 假设编译器可以处理错误1,但是,你可能会得到“Base class not defined”错误,因为[A]被编译,在编译A之前,所有包含的标题([B]和[C])都是编译。 C被编译为A和B的子类,但此时甚至不存在嘿,B和A!这是前瞻性声明的便利之处。它允许我说“有2个类,B和C,仍然没有编译”,并且在cpp文件中实际使用了头文件
但是这个解决方案仍然存在一些问题。您只能使用前向声明为指针和引用的类。但是,即便如此,也建议将对象作为引用或const引用传递。所以你可以在[A]中使用C和B作为参考。