【问题标题】:Checking header file for dependencies at compile-time在编译时检查头文件的依赖关系
【发布时间】:2013-07-10 11:05:12
【问题描述】:

编译器是否提供自动检查每个源文件(及其关联的头文件,如果有)是否包含所有其他所需头文件的功能?或者至少发出警告,例如,如果未明确包含所需的标头?

例如,我希望编译器在我执行以下操作时报告:

header1.h

#include <string>
...

header2.h

#include "header1.h"
#include <iostream>
std::string blah;    //<-- issue warning here, <string> not included explicitly
...

source2.cpp

#include "header2.h"
...
cout << endl;        //<-- issue warning here, <iostream> not included explicitly

我正在使用 g++ 和 Visual Studio,所以我的问题主要适用于这些编译器。谢谢!

【问题讨论】:

  • 编译器会告诉你,但不会告诉你你忘记包含一些特定的文件。您必须自己从错误消息中推断出这些信息。
  • 当编译器看到 包含在 header1.h 中时,当您在 header2.h 中使用它时不会给出任何报告,因为您已经在 header2.h 中包含了 header1.h...我认为这样做是完全可以的,因为 C++ 不喜欢代码重复......
  • 我想知道为什么有两个人对这个问题投了反对票。我希望 cmets 提供一些意见,说明他们为什么认为这个问题没有建设性。
  • 设计头文件是很常见的,因此包含它们是在它们包含的其他一些头文件中进行声明的官方方式。以 g++ 的标准库为例,string 没有在 &lt;string&gt; 中声明,而是在 &lt;bits/basic_string.h&gt; 中声明。会有很多误报,或者你需要一种机制来避免它们......
  • @DanNestor 你的右伙伴,看起来反对投票是最新趋势......他们想在发布问题之前吓唬人......

标签: c++ visual-c++ gcc g++


【解决方案1】:

据我所知,没有自动的方法可以做到这一点。

我的建议是将包含在标题中的内容仅限于 .h 中定义的“接口”所需的内容 在 C++ 编码标准(Sutter,Alexandrescu)中,您可以找到一个明确解决此问题的项目(它的标题为 Make header files self-sufficient)。我引用:

负责任地行事:确保您编写的每个标头都是可独立编译的,通过 让它包含其内容所依赖的任何标题

但不要包含您不需要的标题;他们只是创建了杂散的依赖关系。 考虑使用这种技术来帮助实施标头自给自足:在您的构建中,编译 每个标头都被隔离并验证没有错误或警告。

此外,您应该始终首先包含您自己的 .h,因为这样可以最大限度地提高发现是否存在包含错误的可能性。

在所有情况下,标题都应该是可交换的,因此如果您的文件包含 a.h 和 b.h,则两种可能的顺序都应该可以。

【讨论】:

  • 这正是我试图坚持的编码实践,但是我想知道编译器是否无法帮助识别潜在问题。我认为调整翻译单元以便在编译时发现这些问题应该是微不足道的。
  • 正如我所说,据我所知,没有这种可能性。我可以补充一点,如果有的话我可能会知道,至少我想 C++ 编码标准中会提到它,因为他们写过这个问题
  • @DanNestor:“正是我试图遵守的编码实践” - 它与您的问题不同......当 C++ 编码标准说“通过让它包含任何标题,其内容取决于" 他们不一定是直接,这是你的问题试图强制执行的。
  • @DanNestor:也就是说,一些判断很有用:例如如果您包含一个“string_utils”标头,该标头具有许多按值返回字符串并包含&lt;string&gt;的函数,那么您自己包含&lt;string&gt;将是多余且冗长的,但如果您包含的标头不仅仅是偶然使用的字符串 - 比如说拥有f(std::string),那么可以想象维护者可能会转移到 f(const std::string&) 并使用前向声明 - 如果用户不使用该特定功能,则不必包含 &lt;string&gt; 的“好处” - 所以如果你有其他用途 string 你会被烧死的。