在源文件中包含类而不是标题

Posted

技术标签:

【中文标题】在源文件中包含类而不是标题【英文标题】:Include Class in Source File Rather Than Header 【发布时间】:2013-01-17 21:15:40 【问题描述】:

我有 3 个课程:

ClassA.h

ClassA

    public:
        ClassA();
;

ClassB.h

#include "ClassA.h"

classB

    public:
        ClassB();

    private:
        ClassA m_classA;
;

ClassC.h

#include "ClassB.h"

ClassC

    public:
        ClassC();

    private:
        ClassB m_classB;
;

ClassC 需要 ClassB,ClassB 需要 ClassA。 ClassC 不需要 ClassA,所以我应该将 ClassB 标头中的 #include "ClassA.h" 放在源文件中并创建一个全局对象还是有更好的方法?

ClassB.cpp

#include "ClassB.h"
#include "ClassA.h"

ClassA g_classA;

【问题讨论】:

@Rapptz 前向声明没有声明完整的类型,他没有使用指针。 @Nick 我似乎误读了这个问题。 【参考方案1】:

ClassB 有一个ClassA 对象,所以它的类声明需要ClassA 的完整声明。因此,无论ClassC 发生什么,您都需要在ClassB.h* 中包含ClassA.h 标头。

如果您想避免包含标头,您可以做的是存储一个(智能)指向classA 的指针并转发声明它。那么您只需要在classB.cpp 中包含classA.h。这是一个简单的例子:

A.h

class A ;

B.h

#include <unique_ptr>

class A; // forward declaration of A

class B 
 public:
  B();
 private:
  std::unique_ptr<A> a_; // C++11 smart pointer expressing unique ownership
;

B.cpp

#include "B.h"
#include "A.h" // we need the full declaration here.

B::B() : a_(new A()) 

* 严格来说,ClassA.h 可以包含在其他文件中,只要它间接包含在 ClassB.h 中即可。但最好在需要的地方包含您需要的内容,而不是依赖于间接包含。

【讨论】:

对于编写的代码绝对正确,但是...您可以使用 pimpl 来打破依赖关系。 包含ClassA.h 之前 ClassB.h 与包含它inside ClassB.h 一样有效。这可能是个好建议,但不是唯一的方法。 @MarkRansom 是的,我为此添加了一个脚注。 如果您正在处理一个大型项目并且 ClassB 开始变得更大并且包含多个类,您是否仍将所有这些标题包含在 ClassB 的标题中并在那里创建对象。还是在 ClassB 的源文件中包含头文件并创建全局类对象并跳过头文件声明? @JamesMoore “全局类对象”是一个正交概念。对于某种类型的数据成员,就像您拥有的那样,包含类的每个实例都有自己的包含类型的实例。如果你想最小化编译时依赖,你可以做的是让你的类持有(智能)指向其他类型的指针,并在头文件中转发声明这些类型而不是包含它们的头文件。然后在源文件中包含头文件。我将添加一个小例子。

以上是关于在源文件中包含类而不是标题的主要内容,如果未能解决你的问题,请参考以下文章

如何让我的主文件包含类的 .h fie?

组织 Eclipse 插件文件的导入

CoreData - 更新模型类而不是创建新的

由 qt-designer 命名类而不是手动命名

在 JSP 中包含/导入文件之前,如何检查文件是不是存在?

能够在 ASP.NET 中包含文件,但不检查它是不是存在