我应该包括每个标题吗?

pet*_*555 17 c++ c++11

我是否应该包括每个标题,即使之前包括它?或者我可以尽可能地避免它?例如.如果我使用std::stringstd::vector在某些文件中.如果<string>包含<vector>我应该只包括<string><string><vector>

Nia*_*all 29

如果在文件中使用与标头相关的实体(例如某种类型),则应为其包含相关标头.不要依赖标题来互相包含.如果您使用它,请包含它.

C++标准库不要求列入<string><vector>,也不反之亦然.尝试使用这样的功能会将代码限制为特定的实现.通常,标准库头可能会或可能不会以未指定的顺序或方式包含其他标头(或它们自己的内部标头).一个值得注意的例外是<initializer_list>需要包含在一些其他标准头文件中.也可能发生对这种未指定的顺序或方式的更改,从而破坏了先前使用更新的编译器或更新的标准库实现编译代码(已知这种情况发生).

还要考虑如果头文件是类的定义,那么它应该包括该类定义所需的内容.关联.cpp应包括其关联.h和实现该类所需的其余文件.不需要它,不包括它 ; 不包括超过需要(llvm风格指南).这里有一个例外是模板(没有相关的.cpp) ; 此异常将适用于其他仅标头实现.

值得注意的是,从长远来看,维护包括你使用的东西可能很困难; 因此有意义的是,在编码周期的开始,包括接口所需的内容是很重要的; 然后再次检查包含对代码进行的任何合理更改.

在这方面似乎有一些进展,例如iwyu项目,它使用了clang工具链,似乎也支持msvc.

一个反例是如果标题的原因是包括其他标题,那么也许,但即便如此,我会非常小心 - 确保它明确定义了它包含的内容.一个例子可以是预编译头.

  • 您可能还想提一下,对于自己的C++文件,`.h`文件中的接口应该只包含用于接口的头,但`.cpp`文件中的实现将包含实现所需的所有内容. . (9认同)
  • 我在理论上同意这种观点.不幸的是,如果你滑倒就很难检测到它. (3认同)

das*_*ght 8

通常,您应该将头依赖项视为实现的一部分,而不是作为接口的一部分.

您不应该依赖包括其他标头的标头.如果你的班级需要使用a std::vector,include <vector>; 如果你需要std::string,包括<string>.否则,当过去包含文件的标题突然停止包含它时,您会为自己设置意外故障,因为它们不再需要它.