c++头文件不包含任何其他头文件的任何好理由

Any good reason for C++ header file to not include any other header files?

本文关键字:文件 理由 其他 任何好 包含任 何其他 c++      更新时间:2023-10-16

我见过这样的头文件包含样式,其中头文件不包含其他头文件,相应的*.cpp文件必须包含所有依赖项(并以正确的顺序包含它们)。在过去的美好日子里,这似乎可能使构建依赖关系跟踪更容易(但我只是猜测)。现在有什么好的理由吗?

文件"B.h":

#ifndef _B_h_
#define _B_h_
// Note we do not #include "A.h" that contains class A declaration.
class B
{
public:
   A a; // An A object.
};
#endif // _B_h_
文件"B.cpp":

#include "A.h" // Must include this before B.h, otherwise class A not defined in B.h
#include "B.h"
...

是的,这是不好的做法,因为如果有人弄错了顺序他们就会得到错误,他们可能无法弄清楚。如果所有的头文件都包含了守卫,那么一个头文件包含了它需要的所有其他头文件就不会有问题,这就是它应该有的样子。

似乎写这段代码的人误解了减少包含头文件数量的一般建议。通常建议删除不必要的 #include <>指令,以期加快编译速度。实际上,在大型项目中,它可以通过以下方式显著加快编译速度:

  1. 减少编译器需要打开的头文件数量来编译任何给定的源文件;
  2. 减少头文件更改后需要重新编译的源文件的数量。

一般来说,人们会建议(这是我参与的所有项目的编码标准)对类使用前向声明,除非在相关头文件中定义的类是:

  1. 用作基类;
  2. 用作数据成员;
  3. 有一个不完整的官方规范(例如,标准库容器允许有额外的模板参数,只要它们有默认值,所以转发声明它们是不标准的)。

在情形1和2中,#include <>指令必须出现在所有依赖的源文件和头文件中的类定义之前。基本上,它只是移动#include <>指令(s)从头到它的每一个依赖关系。它导致更多的代码,这样做没有任何好处(例如编译时间等将是相同的)。由于这个原因,这个建议还伴随着编码标准中的另一个条目:每个头文件应该"独立"编译(例如,包含在源文件的第一行)。

这是一个非常糟糕的做法。让编译器找出正确的顺序——这样更不容易出错。头文件应该像它们自己被包含一样编译——也就是说,如果您有一个仅由#include "B.h"组成的TU。

现在有好的理由吗?

不,不完全是。人们做各种各样"会起作用"的事情,要么是因为他们不知道更好的方法,要么是因为他们不在乎,要么是因为他们有更重要的事情要担心。当你的语言依赖于一个预处理器而不是一个真正的模块导入系统时,就会发生这种情况。

我想说最好的做法是确保包含你的东西的人永远不必担心包含的顺序或隐藏的先决条件。除非你的手被一些第三方愚蠢的宏技巧所强迫,无论如何。

是的,我建议在任何头文件中#包括' INTERFACE的任何依赖项。

在这种情况下,是的:我将#包括"A"(因为B的接口依赖于A)。

否则,如果实现使用"A"(但头文件没有),我只会在.cpp中#包含A(因为它不是接口的一部分)。

在任何情况下,如果可以避免的话,我都不希望标题的顺序有问题。一般来说,标题的顺序不重要。

IMHO…

PS:正如Bjarne Stroustrup所希望的那样,预处理器和预处理器宏仍然与我们同在。当然在c语言中,当然在任何微软API中。尊重这个事实才是好形式。

我会认为这种风格很糟糕。这会导致很难理解错误。

这样做的原因可能是为了避免每次更改单个头文件时重新编译大量代码。如果你发现自己在这种情况下,你可能有一个设计问题。