我必须重构一个旧代码.它的一个问题是它超过了无用的"包括".在同一个项目中,我看到了以下语法:
#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)
我想弄明白:
声明一个这样的类:
class AnotherClass;
Run Code Online (Sandbox Code Playgroud)
被称为前瞻宣言.它允许编译器知道类的存在,在不需要知道类的详细信息的情况下,就像在您发布的场景中一样.
通常,如果您不打算使用该类的实例,那么您只需处理指针而不调用其上的任何方法,您不需要知道除类名之外的任何内容.这可以加速大型项目的编译.
要理解差异,您必须首先理解编译器为什么需要include.
编译器必须知道您声明的每个类的大小.因此,它必须知道您添加到类中的每个成员的大小.对于非指针非内置成员,编译器必须查看该成员类的定义,该成员类通常位于必须包含的标头中.在指针的情况下,编译器不必查看整个定义,因为无论其类型如何,指针在给定平台上总是具有相同的大小(通常为32或64位).因此,当成员是指针时,编译器只需要知道名称,这可以通过前向声明来完成,即
class AnotherClass;
Run Code Online (Sandbox Code Playgroud)
现在,哪一个使用?
保持简短:尽可能使用前向声明,包括必要时.
如果您的标题可以通过前向声明完成,那么您将减少整个编译时间,因为您包含的每个标题都必须在包含它的每个翻译单元中处理.
一种常见的方案是在标头中转发声明,并在相关的包含中包含相应的类.cpp.
这是两件不同的事情:
#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)
| 归档时间: |
|
| 查看次数: |
1338 次 |
| 最近记录: |