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

nav*_*vid 5 c++ declaration

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

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是一个类,因为我在第一次传递时看到了这个定义".

  • 我很奇怪C和C++期望编译器在类范围方面是单通道的,只是在汇编代码编译中解析标签需要*that*编译器无论如何要进行两次传递.程序员要求特定的声明命令似乎过于繁琐. (2认同)

Tob*_*ner 7

如果访问该类的成员/方法或者需要知道大小,则编译器需要定义类.在其他情况下,前瞻性声明就足够了.这节省了编译时间.例:

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

感谢您关于循环依赖关系的评论,我只是忘记了它们.


phi*_*mue 4

首先,声明该类,然后定义该类。

声明:它只是告诉编译器:好的,这里有一些东西(方法,类等),可以通过给定的名称使用。它只是将给定的名称绑定到某个东西。

定义:它告诉编译器:好的,这是方法、类等实际执行的操作(以及如何执行)。如果定义了某些内容,则会导致编译器实际为其分配空间。

你也许可以看一下这里