在 cpp 文件中声明转发的类定义,干什么

Declare a forwarded class definition in a cpp file, what for?

本文关键字:定义 干什么 转发 cpp 文件 声明      更新时间:2023-10-16

.cpp文件中转发类定义有什么意义?

想象一下,我在另一个公共类中有一个私人类。我转发私有类的定义,如私有类。

将我的私有类的声明放在.cpp文件中有什么好处,或者我应该在我的公共类.h中坚持我的前向声明并将我的privateClass.h包含在cpp文件中?

内部类和结构通常最好远离公共标头,以避免依赖和耦合。

如果内容在公共标头中,

则意味着如果实现细节(在您的私有类/结构中)发生变化,则公共标头将不得不更改。这很糟糕,因为客户端程序实际上需要重新编译(在 ODR - 一个定义规则下),并且各种实现定义了对类/vtable 布局和/或名称重整的后果。

一旦您可以避免依赖于完整私有类型的定义,您将避免拥有所有不需要的依赖项,从而导致

  1. 缩短重建时间
  2. 避免客户端代码对实现私有详细信息的意外依赖

向前声明的类在定义之前被称为"不完整类型"(通常在私有头文件中或仅在 cpp 文件本身中)。在那一刻之前,只允许地址、引用、按引用传递或按指针传递。有时不完整的类会导致棘手的语义情况;不完整类型的对象销毁将假定非虚拟析构函数(某些编译器可以检测到这一点,并在实际定义引入虚拟析构函数时发出警告)。这在定义不完整类型的智能指针时起着重要作用,例如在流行的 pImpl 习语中。如有疑问,请随时使用智能指针库的文档(例如 Boost SmartPtr)。

更新添加后台程序链接,因为这得到了一个流行的答案:

  • Boost shared_ptr<>构造函数需要完整类型
  • 39.11 如何创建两个彼此了解的类?
  • 39.12 前向声明与成员对象一起使用时需要哪些特殊注意事项?
  • 39.13 前向声明与内联函数一起使用时需要哪些特殊注意事项?
  • 39.14 为什么我不能在 std::vector<> 中放置一个前向声明的类?

原因是您的.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。

请记住,您可以在多个模块中声明类型,但只能在其中一个模块中定义类型。