C++中include指令和前向声明之间的区别

cri*_*eng 6 c++

我必须重构一个旧代码.它的一个问题是它超过了无用的"包括".在同一个项目中,我看到了以下语法:

#include <AnyClass> //A system header
#include "AnotherAnyClass" //A application header

class AnotherClass;

class Class : public OneMoreClass
{

public:
    explicit Class();
    ~Class();

private:
    AnotherClass *m_anotherClass;

}
Run Code Online (Sandbox Code Playgroud)

我想弄明白:

  1. "包含"类"和"类类"之间有什么区别?
  2. 应该何时使用第二种方法以及如何使用?

Nic*_*eys 7

声明一个这样的类:

class AnotherClass;
Run Code Online (Sandbox Code Playgroud)

被称为前瞻宣言.它允许编译器知道类的存在,在不需要知道类的详细信息的情况下,就像在您发布的场景中一样.

通常,如果您不打算使用该类的实例,那么您只需处理指针而不调用其上的任何方法,您不需要知道除类名之外的任何内容.这可以加速大型项目的编译.

  • 你没有解释这与`#include`的区别. (2认同)

JBL*_*JBL 5

要理解差异,您必须首先理解编译器为什么需要include.

编译器必须知道您声明的每个类的大小.因此,它必须知道您添加到类中的每个成员的大小.对于非指针非内置成员,编译器必须查看该成员类的定义,该成员类通常位于必须包含的标头中.在指针的情况下,编译器不必查看整个定义,因为无论其类型如何,指针在给定平台上总是具有相同的大小(通常为32或64位).因此,当成员是指针时,编译器只需要知道名称,这可以通过前向声明来完成,即

class AnotherClass;
Run Code Online (Sandbox Code Playgroud)

现在,哪一个使用?

保持简短:尽可能使用前向声明,包括必要时.

如果您的标题可以通过前向声明完成,那么您将减少整个编译时间,因为您包含的每个标题都必须在包含它的每个翻译单元中处理.

一种常见的方案是在标头中转发声明,并在相关的包含中包含相应的类.cpp.


Mar*_* A. 5

这是两件不同的事情:

#include <AnyClass>
Run Code Online (Sandbox Code Playgroud)

这是标题(或任何类型的文本)文件的常规包含.它等同于AnyClass在您键入包含指令的位置粘贴文件的内容(这就是为什么包含保护和/或编译器编译指示通常用于防止同一文件中的多个包含).

这个语法:

class AnotherClass;
Run Code Online (Sandbox Code Playgroud)

是一个前向声明,它通知编译器AnotherClass类的存在.它在许多场景中都很有用,例如假设你有两个类,每个类需要一个指向另一个的指针:

class ClassB {
    ClassA* pointer_to_classA;
};
class ClassA {
    ClassB* pointer_to_classB;
};
Run Code Online (Sandbox Code Playgroud)

上面的代码将生成一个错误:" 错误:未知类型名称'ClassA' ",因为您使用的ClassA类型没有编译器知道它是什么(还).编译器的解析器只有ClassA在解析类声明的开头时才会知道它的存在.

要完成上述工作,您需要一个前瞻性声明:

class ClassA; // A ClassA type exists

class ClassB {
    ClassA* pointer_to_classA;
};
class ClassA {
    ClassB* pointer_to_classB;
};
Run Code Online (Sandbox Code Playgroud)