前瞻性声明的目的是什么?

时间:2010-06-24 12:58:22

标签: c++ declaration

这是什么描述或含义: 例如:

class test;

class test
{
  .....
};

6 个答案:

答案 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)

简单的答案是,当您使用第一个表单时,您可以保留指针或对类的引用,而无需完整实现。当两个类紧密交互并且它们的实现或定义难以分离时,这非常有用。