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

时间:2014-10-23 14:02:35

标签: 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;

}

我想知道:

  1. 'include'Class''和'class Class'之间有什么区别?
  2. 何时应该使用第二种方法以及如何使用?

3 个答案:

答案 0 :(得分:7)

声明一个这样的类:

class AnotherClass;

称为Forward Declaration。它允许编译器知道类的存在,在不需要知道类的详细信息的情况下,例如在您发布的场景中。

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

答案 1 :(得分:5)

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

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

class AnotherClass;

现在,使用哪一个?

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

如果您的标题可以使用转发声明完成,那么您将减少整个编译时间,因为您包含的每个标题都必须在包含它的每个翻译单元中进行处理。

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

答案 2 :(得分:5)

这是两件不同的事情:

#include <AnyClass>

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

此语法:

class AnotherClass;

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

class ClassB {
    ClassA* pointer_to_classA;
};
class ClassA {
    ClassB* pointer_to_classB;
};

以上代码将生成错误:“错误:未知类型名称'ClassA'”,因为您使用了ClassA类型而编译器不知道它是什么(还)。编译器的解析器在解析类声明的开头时只知道ClassA的存在。

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

class ClassA; // A ClassA type exists

class ClassB {
    ClassA* pointer_to_classA;
};
class ClassA {
    ClassB* pointer_to_classB;
};