#include 头文件已经包含在包含的头文件中是常见的做法吗?

Is it common practive to #include header files already included by included header files?

假设我们有一个头文件 A.h,它取决于 B.hC.h 中声明的内容。 B.h 也依赖于 C.h,因此包含它。 在这种情况下,我们不需要在 A.h 中包含 C.h 并且没有它也可以编译得很好。

但我想知道在这些情况下最好的行动方案是什么。如果 B.h 以某种方式改变并且不再依赖于 C.hA.h 将会中断。

另一方面,如果我认为这一直到最后,似乎 unneccessary/impractical 重新包含每个依赖项。

我的一个常见案例是标准库。在我几乎所有的头文件中,我都必须包含 <stdint.h><stdbool.h>。我经常跳过这个,因为它们已经包含在其中一个依赖项中,但这总是让人觉得有点武断。

If B.h somehow changes and no longer depends on C.h, A.h will break.

没错。为什么要抓住机会?

On the other hand if I think this through to the end it seems unneccessary/impractical to reinclude every single dependency.

如果不切实际,则说明您的文件有太多依赖项并且可能太大。

将其重构为更小的模块。

A common case I have are standard libraries. In almost all my header files I would have to include <stdint.h> and <stdbool.h>. I often skip this because they were already included in one of the dependencies but this always feels kind of arbitrary.

我承认有时我会跳过这些,因为我知道我的 headers 之一——明确定义为将我需要的类型纳入范围——已经做到了这一点。它不太可能被重构,因为它有这些headers 因为这个原因,而不是因为一些其他可能消失的依赖关系。

但是,归根结底,在您需要的地方包含 <stdint.h><stdbool.h> 并没有错。老实说,我很惊讶你在 "almost all [your] header files" 中发现你需要它们。

通常的做法——也是我建议的经验法则——所有 header 都应该是 self-contained。

换句话说,如果 A.h 中的内容只有在 B.h#included 时才能编译,那么 A.h 应该 #include "B.h"。这避免了在需要使用 A.h 来执行

时强制使用其他代码
#include "B.h"
#include "A.h"

那就是递归。每个包含的文件都应该是 self-contained。它也适用于您的 headers,包括标准 headers。

为了处理 header 被多次包含的潜在问题,也应该在 header 中使用包含守卫。

与任何经验法则一样,它在某些情况下并不适用。但这些在实践中相对不常见。