这是什么描述或含义: 例如:
class test;
class test
{
.....
};
答案 0 :(得分:21)
C ++(如C)旨在通过单程编译器实现。如果编译器需要知道符号在实际定义类之前引用类,则前向引用是必需的。这个经典的例子是两个类需要包含彼此的指针。即。
class B;
class A {
B* b;
};
class B {
A* a;
};
如果没有对B的前向引用,编译器无法成功解析A的定义,并且您无法通过在A之前放置B的定义来解决问题。
在像C#这样需要双向编译器的语言中,您不需要前向引用
class A {
B b;
}
class B {
A a;
}
因为编译器的第一次传递只是选取所有符号定义。当编译器进行第二次传递时,它可以说“我知道B是一个类,因为我在第一次传递时看到了这个定义”。
答案 1 :(得分:7)
如果访问该类的成员/方法或者需要知道大小,编译器需要定义类。在其他情况下,前瞻性声明就足够了。这节省了编译时间。 示例:
class A {
B m_b;
C* m_ptrC;
};
对于这个类,你需要B的定义(需要的大小),只需要C的声明(指针有固定的大小)。您只需要包含B的标题,而不是C的标题.C的前向声明就足够了。
A.H:
#ifndef A_H
#define A_H
#include <b.h>
class C;
class A
{
B m_b;
C* m_ptrC;
}
#endif
c的前向声明(而不是包括c.h,这也是可能的)可以保存在包含a.h时解析c.h.在大型项目中,这可以节省大量的编译时间。 另一个好处是,在这种情况下,c.h中的更改不会触发a的重新编译。我不知道编译器是否认识到这一点,如果你包含c.h而不是正向声明它。
有关更多信息,请尝试了解pimpl-idiom(只需google for it。您将获得大量点击)。
当然 - 在a.cpp中,如果你实际上用c指针做某事(例如m_ptrC-&gt; Add()),你需要包含c.h.但是a.cpp只读取一次,其中头文件读取n次大n用于大型项目中经常使用的类。
前向声明还允许循环依赖。 例如:
class B;
class A {
B* m_ptrB;
}
class B {
A* m_ptrA;
}
请记住 - 您无法使用任何有关尺寸和尺寸的信息。方法,如果您使用前向声明。这也是两个类相互包含的情况(尽管一个类不需要前向引用)。我个人认为循环引用是不好的风格,如果可能你应该避免它们。
有关其他信息:C++ FAQ
感谢您对循环依赖关系的评论,我只是忘了它们。
答案 2 :(得分:4)
首先,该类是声明,然后是定义的。
声明:它只是告诉编译器:好的,这是给定名称可以使用的东西(方法,类等)。它只是将给定的名称绑定到某个东西。
定义:它告诉编译器:好的,这是方法,类等实际上做什么(以及如何)。如果定义了某些内容,则会使编译器实际为其分配空间。
您可以查看here。
答案 3 :(得分:1)
第一行是所谓的前瞻性声明。它将类的名称带入当前命名空间而不实际定义它。
答案 4 :(得分:0)
test
并在下面定义它,省略了实际的成员(...)。
答案 5 :(得分:0)
简单的答案是,当您使用第一个表单时,您可以保留指针或对类的引用,而无需完整实现。当两个类紧密交互并且它们的实现或定义难以分离时,这非常有用。