【问题标题】:Include File Ordering Strategy包含文件排序策略
【发布时间】:2011-06-19 13:43:49
【问题描述】:

我已经看到相当一致的建议,即实现文件 (.cc / .cpp) 应在包含其他头文件之前包含其相应的类 definition file first。但是当话题转移到头文件本身,以及它们包含的包含顺序时,建议似乎会有所不同。

Google coding standards建议:

  1. dir2/foo2.h(首选位置 - 请参阅下面的详细信息)。
  2. C 系统文件。
  3. C++ 系统文件。
  4. 其他库的 .h 文件。
  5. 您项目的 .h 文件。

目前尚不清楚上述条目 1 和条目 5 之间的区别是什么,以及为什么会选择其中一个或另一个位置。也就是说,another online guide 建议此顺序(可在该文档的“类布局”部分找到):

  1. 系统包括
  2. 项目包括
  3. 本地包括

再次出现歧义,这次是在第 2 项和第 3 项之间。有什么区别?这些代表项目间和项目内包含吗?

但更重要的是,两个提议的编码标准似乎都建议最后包含“你的”头文件。这样的建议,与建议在实现文件中包含排序相反,并不直观。将“您的”头文件始终列在首位——在系统头文件和第 3 方头文件之前是否没有意义?

【问题讨论】:

  • 1 和 5 之间的区别由“在 dir/foo.cc 中,其主要目的是实现或测试 dir2/foo2.h 中的内容,命令您的包含如下:”备注在 1-5 列表的正上方。
  • Header file order 的可能副本

标签: c++ include coding-style header-files


【解决方案1】:

对于标题: 这个项目的标题 其他项目标题 第 3 方标头 C++ 头文件

对于来源: 此源文件的标头 这个项目的标题 其他项目标题 第 3 方标头 C++ 头文件

此命令最大限度地减少了在 .hpp 文件中遗漏某些必需标头的机会。它还最大限度地减少了第 3 方标头等的 INTERSECTIONS。并且所有 hpp 模块都以最低要求的依赖项进行编译。

例如: ->test.hpp

// missing #include <string> header
void test(std::string& s);

->test.cpp

#include <string> 
#include "test.hpp"
// we hide bug with missing required header 

->test2.cpp

#include "test.hpp"
#include <string> 
// compilation error with missing header

【讨论】:

    【解决方案2】:

    关于谷歌的风格:

    完全没有歧义。

    包含的第一个标头应该是与 this 源文件相关的标头,因此位于位置 1。这样可以确保它包含所需的任何内容并且没有“隐藏”依赖关系:如果有,它'将立即暴露并阻止编译。

    如果问题发生在您更有可能更改的标题中,则其他标题从您最不可能更改的标题中排序。问题可能是标识符冲突、宏泄漏等......

    根据定义,C 和 C++ 系统标头很少更改,仅仅是因为使用它们的人太多,因此它们排在第二位。

    第三方代码可以更改,但一般比较麻烦且需要时间,因此他们排在第三位。

    “项目包含”是指项目范围的包含,通常是由多个项目使用的自制库(中间件)。它们可以更改,但这也会影响其他项目,它们排在第四位。

    最后是“本地包含”,即特定于该项目的那些文件,可以在不影响其他任何人的情况下进行更改。如果出现问题,那些是主要候选人,他们排在最后。

    请注意,实际上您可以拥有更多层(尤其是在软件商店中),关键思想是从底层(系统库)到顶层对依赖项进行排序。

    在给定的层中,我倾向于按字母顺序组织它们,因为这样更容易检查它们。

    【讨论】:

      【解决方案3】:

      从技术角度来看,您列出包含的顺序应该无关紧要。如果你设计得当,你应该可以把它们按你想要的任何顺序排列,它仍然可以工作。例如,如果您的foo.h 需要&lt;string&gt;,则它应该包含在您的foo.h 中,这样您就不必在任何使用foo 的地方记住该依赖关系。

      话虽如此,如果你确实有顺序依赖,大多数时候把你的定义文件放在最后会解决它。那是因为foo.h 依赖于&lt;string&gt;,而不是相反。

      您可能认为将定义文件放在最后是一个很好的例子,但实际上恰恰相反。如果您的编码标准首先需要定义,那么您的编译器更有可能在首次编写时捕获不正确的顺序依赖关系。

      【讨论】:

      • If your coding standards require the definition first, your compiler is more likely to catch incorrect order dependencies when they are first written。是的,这是我问题的前提。那么为什么其他指南中似乎会推荐相反的方法呢?
      • @BrentArias:仅仅是因为其他指南的作者要么没有考虑过,要么不重视这个简单但非常有用的检查。
      【解决方案4】:

      我不知道任何逐字标准,但作为一般经验法则,包括尽可能少的头文件,尤其是在其他头文件中,以减少编译时间、冲突和依赖性。我喜欢在头文件中使用类的前向声明,并且只要我能负担得起,就只在 .cpp 端包含头文件和定义。

      也就是说我的个人喜好如下:

      对于标题:

      1. C++ 头文件
      2. 第三方标头
      3. 其他项目标题
      4. 此项目的标题

      来源:

      1. 预编译头文件
      2. 此源文件的标头
      3. C++ 头文件
      4. 第三方标头
      5. 其他项目标题
      6. 此项目的标题

      指针或建议通常是为了避免冲突和循环引用,否则这完全是个人喜好或您希望在协作项目中遵守的任何政策。

      【讨论】:

      • 理论上,让“这个/其他项目的标题”出现在 C++ 和第 3 方标题之前对您没有帮助吗?它会防止意外的依赖隐藏,是吗?
      • 是的,这可能是真的,除非我在开​​头段落中提到,如果任何头文件中包含任何头文件,我通常很少...
      • @Brent:如果每个标头都已经在其自己的源中进行了测试,则不会。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-30
      • 2021-05-26
      • 1970-01-01
      相关资源
      最近更新 更多