【发布时间】:2018-02-04 05:15:39
【问题描述】:
在 .cpp 文件中转发类定义有什么意义?
想象一下,我在另一个公共课程中拥有一个私人课程。我转发私有类的定义,比如Private类。
将我的私有类的声明放在 .cpp 文件中是否有任何好处,或者我应该坚持在我的 public class.h 中使用我的前向声明并将我的 privateClass.h 包含在 cpp 文件中?
【问题讨论】:
在 .cpp 文件中转发类定义有什么意义?
想象一下,我在另一个公共课程中拥有一个私人课程。我转发私有类的定义,比如Private类。
将我的私有类的声明放在 .cpp 文件中是否有任何好处,或者我应该坚持在我的 public class.h 中使用我的前向声明并将我的 privateClass.h 包含在 cpp 文件中?
【问题讨论】:
内部类和结构通常最好远离公共标头以避免依赖和耦合。
如果公共标头中有内容,则意味着如果实现细节(在您的私有类/结构中)发生更改,则公共标头必须更改。这很糟糕,因为客户端程序实际上需要重新编译(根据 ODR - 一个定义规则)并且各种实现定义了类/vtable 布局和/或名称修改的后果。
一旦你可以避免依赖于你的 complete 私有类型的定义,你将避免拥有所有不需要的依赖,从而导致
前向声明的类在定义之前称为“不完整类型”(通常在私有头文件中或仅在 cpp 文件本身中)。在那之前,只允许寻址、引用、按引用传递或按指针传递。 有时不完整的类会导致棘手的语义情况;不完整类型的对象破坏将假定一个非虚拟析构函数(一些编译器可以检测到这一点并在实际定义引入虚拟析构函数时发出警告)。这在定义不完整类型的智能指针时起着重要作用,例如在流行的 pImpl 成语中。如有疑问,请使用智能指针库的文档(例如 Boost SmartPtr)。
更新添加背景链接,因为这是一个流行的答案:
【讨论】:
原因是您的.h 文件应该只包含描述您的模块接口的代码,该接口由公共类表示。在这种情况下,Private 类的声明和定义是关于模块接口的一个实现,并没有带来如何使用接口的信息。
【讨论】:
前向声明的要点是能够在没有定义的情况下使用该类。您可以只转发声明类 Private,并使用指向该类对象的指针或引用,而不包括任何标题或在该或包含的文件中定义类本身。
如果您将私有类声明放入头文件中,那么基本上它不再是私有的,因为任何人都可以包含该文件。因此,要么将其隐藏在另一个类的声明中,要么在可能的情况下将其声明在 cpp 文件中。
【讨论】:
类转发通常用在头文件中。例如:
// Class2.h
class Class1;
class Class2
{
Class1* m_class1; // Using Class1 type
};
这允许 Class2.h 使用 Class1 而不必在其头文件中包含 Class1.h。当然,任何包含 Class2.h 的 .cpp 文件也必须包含 Class1.h。
请记住,您可以在多个模块中声明类型,但您只能在其中一个中定义类型。
【讨论】: