这是什么描述或含义:例如:
class test;
class test
{
.....
};
Run Code Online (Sandbox Code Playgroud)
Fer*_*cio 22
C++(如C)旨在通过单程编译器实现.如果编译器需要知道符号在实际定义类之前引用类,则前向引用是必需的.这个经典的例子是两个类需要包含彼此的指针.即
class B;
class A {
B* b;
};
class B {
A* a;
};
Run Code Online (Sandbox Code Playgroud)
如果没有对B的前向引用,编译器无法成功解析A的定义,并且您无法通过在A之前放置B的定义来解决问题.
在像C#这样需要双向编译器的语言中,您不需要前向引用
class A {
B b;
}
class B {
A a;
}
Run Code Online (Sandbox Code Playgroud)
因为编译器的第一次传递只是选取所有符号定义.当编译器进行第二次传递时,它可以说"我知道B是一个类,因为我在第一次传递时看到了这个定义".
如果访问该类的成员/方法或者需要知道大小,则编译器需要定义类.在其他情况下,前瞻性声明就足够了.这节省了编译时间.例:
class A {
B m_b;
C* m_ptrC;
};
Run Code Online (Sandbox Code Playgroud)
对于这个类,您需要定义B(需要的大小)并且只需要C的声明(指针具有固定大小).您只需要包含B的标题,而不是C的标题.C的前向声明就足够了.
啊:
#ifndef A_H
#define A_H
#include <b.h>
class C;
class A
{
B m_b;
C* m_ptrC;
}
#endif
Run Code Online (Sandbox Code Playgroud)
c的前向声明(而不是包括ch也是可能的)可以节省你在每次包含时解析ch啊在大型项目中,这可以节省大量的编译时间.另一个好处是,在这种情况下,ch中的更改不会触发a的重新编译.我不知道如果你包含ch而不是前面声明它,编译器是否会识别它.
有关更多信息,请尝试了解pimpl-idiom(只需google for it.您将获得大量点击).
当然 - 在a.cpp中,如果你实际上用c指针做某事(例如m_ptrC-> Add()),你需要包含ch但a.cpp只读一次头文件被读n次对于在大型项目中经常使用的类,使用大n.
前向声明还允许循环依赖.例:
class B;
class A {
B* m_ptrB;
}
class B {
A* m_ptrA;
}
Run Code Online (Sandbox Code Playgroud)
请记住 - 如果使用前向声明,则不能使用有关大小和方法的任何信息.这也是两个类相互包含的情况(尽管一个类不需要前向引用).我个人认为循环引用是不好的风格,如果可能你应该避免它们.
有关其他信息:C++ FAQ
感谢您关于循环依赖关系的评论,我只是忘记了它们.