C++ 包含在头文件中与转发声明和包含在.cpp中

C++ 包含在头文件中与转发声明和包含在.cpp中,c++,header-files,C++,Header Files,我有一个B组,我想召集a组的成员。所以: 一, 二, 当一个小项目没有太多依赖性时,哪种方法更好?这两种方法相似吗?只需在类a的头中声明类即可 class B; 第二个更好。它使您使用.h文件包含的Ba类模块。考虑下面的子类 b>代码>,并更新 < >使用 c>代码>。在第二种情况下,只替换标题#include和A的组成。在第一种情况下,您必须更改转发声明。另外,在第二种情况下,您定义的不仅仅是符号B 正如在注释中一样,如果头文件与代码的其余部分位于同一目录中,您应该使用#include“B

我有一个B组,我想召集a组的成员。所以:

一,

二,


当一个小项目没有太多依赖性时,哪种方法更好?这两种方法相似吗?

只需在类a的头中声明类即可

class B;

第二个更好。它使您使用
.h
文件包含的
B
a类模块。考虑下面的子类<代码> b>代码>,并更新<代码> < <代码> >使用<代码> c>代码>。在第二种情况下,只替换标题
#include
A
的组成。在第一种情况下,您必须更改转发声明。另外,在第二种情况下,您定义的不仅仅是符号
B


正如在注释中一样,如果头文件与代码的其余部分位于同一目录中,您应该使用
#include“B.h”

那么您所做的就是所谓的前向减容,您希望这样做的原因是,如果您有类似于使用B类的类以及使用A类的B类

在只有一种关系的情况下,您当然可以使用第二种选择。
如果您需要双重使用,那么您的类Declaration中至少有一个必须使用forward Declaration

回答:1
看看



(密歇根大学ECES系的David Kieras)说:

准则#10如果类型X的声明不完整,则使用 而不是#包括其标题X.h。如果另一个结构或类 类型X在的内容中仅显示为指针或引用类型 标题文件,则不应包含X.h,而应仅放置一个 不完整的X声明(也称为“向前”声明)靠近 标题文件的开头,如:
class X参见讲义
有关此功能强大且
有价值的技术。请注意,标准库包含一个标题
通常适用于
库,名为
#尽可能包括
,因为
标题文件非常大(巨大的模板!)


第一种方法是向前声明。你的第二个班实际上包括B班

什么时候使用一个而不是另一个

在以下情况下使用第一个选项:
  • 在A的定义中,只有指向B的指针,即不是B的成员
  • 从A的定义中,您从未调用B的任何函数(即,对B的成员函数的所有调用都发生在.cpp文件中,您在该文件中实际实现了A的成员函数)
  • 您希望类B的接口或大小经常更改,但A的接口不会更改。这样,如果B更改,则只会重新编译A.cpp的内容,而A.h(以及包含A.h的其他文件)不需要更改
在以下情况下使用第二个选项:
  • 您需要知道B的大小。编译器使用类定义和所有成员的大小计算类的大小。例如,如果类A有一个类型为B的成员,那么要计算A的大小,编译器需要知道B的大小;要知道B的大小,需要包括B.h。
    • 您需要调用类B的函数。为了知道您调用的函数是否实际存在,编译器需要知道类B的接口,即您需要包含B.h

    • 你的第一种方法是,在
      a.h
      中,B类
      的存在是已知的,但它的定义是未知的。这限制了您可以在
      a.h
      内使用
      B
      执行的操作。例如,可以有
      B*
      类型的变量,但不能有
      B
      类型的变量(因为对于
      B
      类型的变量声明,编译器必须能够看到
      B
      的完整定义)。此外,如果您有类型为
      B*
      的变量,则不能取消对指针的引用(因为也必须知道
      B
      的定义)

      因此,你的第二选择——没有这些问题——是首选,这也是大多数人大部分时间使用的

      这只是第一种方法可能有用的特殊情况。例如:

      • 如果
        .h
        文件相互包含(但是您可能会遇到一些进一步的问题,也与包含防护有关;这通常很难避免)
      • 如果
        b.h
        非常大和复杂,那么您希望尽可能避免包含它,因为它会减慢编译过程

      喜欢:
      #包括“B.h”
      啊,我会小心的。。。
      // A.h
      #include "B.h"
      
      class A 
      { 
      private: 
          B * impl_; 
      }; 
      
      class B;