C/C++ 包含头文件顺序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2762568/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:37:18  来源:igfitidea点击:

C/C++ include header file order

c++c

提问by Anycorn

What order should include files be specified, i.e. what are the reasons for including one header before another?

应该指定包含文件的顺序,即在另一个头之前包含一个头文件的原因是什么?

For example, do the system files, STL, and Boost go before or after the local include files?

例如,系统文件、STL 和 Boost 是在本地包含文件之前还是之后?

回答by squelart

I don't think there's a recommended order, as long as it compiles! What's annoying is when some headers require other headers to be included first... That's a problem with the headers themselves, not with the order of includes.

我认为没有推荐的顺序,只要它编译即可!令人讨厌的是,当某些标头要求首先包含其他标头时……这是标头本身的问题,而不是包含顺序的问题。

My personal preference is to go from local to global, each subsection in alphabetical order, i.e.:

我个人的偏好是从本地到全球,每个小节按字母顺序排列,即:

  1. h file corresponding to this cpp file (if applicable)
  2. headers from the same component,
  3. headers from other components,
  4. system headers.
  1. 这个cpp文件对应的h文件(如果有的话)
  2. 来自同一组件的标题,
  3. 来自其他组件的标头,
  4. 系统标题。

My rationale for 1. is that it should prove that each header (for which there is a cpp) can be #included without prerequisites. And the rest just seems to flow logically from there.

我对 1. 的理由是它应该证明每个标题(有一个 cpp)可以在#include没有先决条件的情况下被d。其余的似乎只是从那里合乎逻辑地流动。

回答by Nathan Paul Simons

The big thing to keep in mind is that your headers should not be dependent upon other headers being included first. One way to insure this is to include your headers before any other headers.

要记住的重要一点是,您的标题不应依赖于首先包含的其他标题。确保这一点的一种方法是在任何其他标题之前包含您的标题。

"Thinking in C++" in particular mentions this, referencing Lakos' "Large Scale C++ Software Design":

“Thinking in C++”特别提到了这一点,引用了 Lakos 的“Large Scale C++ Software Design”:

Latent usage errors can be avoided by ensuring that the .h file of a component parses by itself – without externally-provided declarations or definitions... Including the .h file as the very first line of the .c file ensures that no critical piece of information intrinsic to the physical interface of the component is missing from the .h file (or, if there is, that you will find out about it as soon as you try to compile the .c file).
可以通过确保组件的 .h 文件自行解析来避免潜在的使用错误 - 无需外部提供的声明或定义......将 .h 文件包含为 .c 文件的第一行可确保没有关键部分.h 文件中缺少组件物理接口固有的一些信息(或者,如果有,您将在尝试编译 .c 文件时立即发现)。

That is to say, include in the following order:

也就是说,按以下顺序包含:

  1. The prototype/interface header for this implementation (ie, the .h/.hh file that corresponds to this .cpp/.cc file).
  2. Other headers from the same project, as needed.
  3. Headers from other non-standard, non-system libraries (for example, Qt, Eigen, etc).
  4. Headers from other "almost-standard" libraries (for example, Boost)
  5. Standard C++ headers (for example, iostream, functional, etc.)
  6. Standard C headers (for example, cstdint, dirent.h, etc.)
  1. 此实现的原型/接口标头(即对应于此 .cpp/.cc 文件的 .h/.hh 文件)。
  2. 根据需要,来自同一项目的其他标题。
  3. 来自其他非标准、非系统库(例如 Qt、Eigen 等)的标头。
  4. 来自其他“几乎标准”的库(例如 Boost)的头文件
  5. 标准 C++ 头文件(例如,iostream、函数式等)
  6. 标准 C 头文件(例如,cstdint、dirent.h 等)

If any of the headers have an issue with being included in this order, either fix them (if yours) or don't use them. Boycott libraries that don't write clean headers.

如果任何标题在包含在此顺序中存在问题,请修复它们(如果是您的)或不使用它们。抵制不编写干净标头的库。

Google's C++ style guideargues almostthe reverse, with really no justification at all; I personally tend to favor the Lakos approach.

谷歌的C ++风格指南认为几乎相反,与所有真的没有理由; 我个人倾向于支持 Lakos 方法。

回答by paxdiablo

I follow two simple rules that avoid the vast majority of problems:

我遵循两个简单的规则来避免绝大多数问题:

  1. All headers (and indeed anysource files) should include what they need. They should notrely on their users including things.
  2. As an adjunct, all headers should have include guards so that they don't get included multiple times by over-ambitious application of rule 1 above.
  1. 所有的头(实际上任何的源文件)应该包括他们需要什么。他们应该依赖于他们的用户,包括东西。
  2. 作为辅助,所有标题都应该包含保护,这样它们就不会因为过于雄心勃勃地应用上面的规则 1 而被多次包含在内。

I also follow the guidelines of:

我也遵循以下准则:

  1. Include system headers first (stdio.h, etc) with a dividing line.
  2. Group them logically.
  1. 首先包含带有分隔线的系统头文件(stdio.h 等)。
  2. 将它们按逻辑分组。

In other words:

换句话说:

#include <stdio.h>
#include <string.h>

#include "btree.h"
#include "collect_hash.h"
#include "collect_arraylist.h"
#include "globals.h"

Although, being guidelines, that's a subjective thing. The rules on the other hand, I enforce rigidly, even to the point of providing 'wrapper' header files with include guards and grouped includes if some obnoxious third-party developer doesn't subscribe to my vision :-)

虽然,作为指导方针,这是一个主观的事情。另一方面,如果某些令人讨厌的第三方开发人员不同意我的愿景,我会严格执行规则,甚至提供带有包含保护和分组包含的“包装器”头文件的地步:-)

回答by Matthieu M.

To add my own brick to the wall.

把我自己的砖加到墙上。

  1. Each header needs to be self-sufficient, which can only be tested if it's included first at least once
  2. One should not mistakenly modify the meaning of a third-party header by introducing symbols (macro, types, etc.)
  1. 每个标头都需要自给自足,只有首先至少包含一次才能对其进行测试
  2. 不应通过引入符号(宏、类型等)来错误地修改第三方标头的含义。

So I usually go like this:

所以我通常是这样的:

// myproject/src/example.cpp
#include "myproject/example.h"

#include <algorithm>
#include <set>
#include <vector>

#include <3rdparty/foo.h>
#include <3rdparty/bar.h>

#include "myproject/another.h"
#include "myproject/specific/bla.h"

#include "detail/impl.h"

Each group separated by a blank line from the next one:

每组与下一组之间用空行分隔:

  • Header corresponding to this cpp file first (sanity check)
  • System headers
  • Third-party headers, organized by dependency order
  • Project headers
  • Project private headers
  • 首先对应于这个 cpp 文件的标题(完整性检查)
  • 系统标题
  • 第三方标头,按依赖顺序组织
  • 项目标题
  • 项目私有标题

Also note that, apart from system headers, each file is in a folder with the name of its namespace, just because it's easier to track them down this way.

另请注意,除了系统头文件外,每个文件都位于一个以其命名空间名称命名的文件夹中,因为这样更容易跟踪它们。

回答by i_am_jorf

I recommend:

我建议:

  1. The header for the .cc module you're building. (Helps ensure each header in your project doesn't have implicit dependencies on other headers in your project.)
  2. C system files.
  3. C++ system files.
  4. Platform / OS / other header files (e.g. win32, gtk, openGL).
  5. Other header files from your project.
  1. 您正在构建的 .cc 模块的标头。(有助于确保项目中的每个标头对项目中的其他标头没有隐式依赖。)
  2. C系统文件。
  3. C++系统文件。
  4. 平台/操作系统/其他头文件(例如 win32、gtk、openGL)。
  5. 项目中的其他头文件。

And of course, alphabetical order within each section, where possible.

当然,在可能的情况下,在每个部分中按字母顺序排列。

Always use forward declarations to avoid unnecessary #includes in your header files.

始终使用前向声明以避免#include头文件中出现不必要的s。

回答by clstrfsck

I'm pretty sure this isn't a recommended practice anywhere in the sane world, but I like to line system includes up by filename length, sorted lexically within the same length. Like so:

我很确定这在理智世界的任何地方都不是推荐的做法,但我喜欢按文件名长度排列系统包含,在相同长度内按词法排序。像这样:

#include <set>
#include <vector>
#include <algorithm>
#include <functional>

I think it's a good idea to include your own headers before other peoples, to avoid the shame of include-order dependency.

我认为在其他人之前包含您自己的标题是个好主意,以避免包含顺序依赖性的耻辱。

回答by wilhelmtell

This is not subjective. Make sure your headers don't rely on being #included in specific order. You can be sure it doesn't matter what order you include STL or Boost headers.

这不是主观的。确保您的标题不依赖于#include按特定顺序排列。您可以确定包含 STL 或 Boost 标头的顺序无关紧要。

回答by Agnel Kurian

First include the header corresponding to the .cpp... in other words, source1.cppshould include source1.hbefore including anything else. The only exception I can think of is when using MSVC with pre-compiled headers in which case, you are forced to include stdafx.hbefore anything else.

首先包含对应于 .cpp... 的标头...换句话说,source1.cpp应该source1.h在包含其他任何内容之前包含。我能想到的唯一例外是当使用带有预编译头的 MSVC 时,您必须stdafx.h在其他任何内容之前包含。

Reasoning:Including the source1.hbefore any other files ensures that it can stand alone without it's dependencies. If source1.htakes on a dependency on a later date, the compiler will immediately alert you to add the required forward declarations to source1.h. This in turn ensures that headers can be included in any order by their dependants.

推理:包括source1.hbefore 任何其他文件可确保它可以独立存在而没有依赖项。如果以后source1.h需要依赖,编译器会立即提醒您将所需的前向声明添加到source1.h. 这反过来确保标题可以按任何顺序包含在其依赖项中。

Example:

例子:

source1.h

源文件1.h

class Class1 {
    Class2 c2;    // a dependency which has not been forward declared
};

source1.cpp

源1.cpp

#include "source1.h"    // now compiler will alert you saying that Class2 is undefined
                    // so you can forward declare Class2 within source1.h
...

MSVC users:I strongly recommend using pre-compiled headers. So, move all #includedirectives for standard headers (and other headers which are never going to change) to stdafx.h.

MSVC 用户:我强烈建议使用预编译的头文件。因此,将#include标准标头(以及其他永远不会更改的标头)的所有指令移至stdafx.h.

回答by dcw

Include from the most specific to the least specific, starting with the corresponding .hpp for the .cpp, if one such exists. That way, any hidden dependencies in header files that are not self-sufficient will be revealed.

从最具体到最不具体,从 .cpp 的相应 .hpp 开始,如果存在这样的文件。这样,头文件中任何不自给自足的隐藏依赖项都将被揭示。

This is complicated by the use of pre-compiled headers. One way around this is, without making your project compiler-specific, is to use one of the project headers as the precompiled header include file.

由于使用预编译头文件,这会变得复杂。解决此问题的一种方法是,在不使您的项目特定于编译器的情况下,使用项目标头之一作为预编译的标头包含文件。

回答by Jimm Chen

It is a hard question in the C/C++ world, with so many elements beyond the standard.

这是 C/C++ 世界中的一个难题,有很多超出标准的元素。

I think header file order is not a serious problem as long as it compiles, like squelart said.

我认为只要编译,头文件顺序就不是一个严重的问题,就像 squelart 所说的那样。

My ideas is: If there is no conflict of symbols in all those headers, any order is OK, and the header dependency issue can be fixed later by adding #include lines to the flawed .h.

我的想法是:如果所有这些头文件中没有符号冲突,那么任何顺序都可以,稍后可以通过在有缺陷的 .h 中添加 #include 行来修复头文件依赖性问题。

The real hassle arises when some header changes its action (by checking #if conditions) according to what headers are above.

当某些标头根据上面的标头更改其操作(通过检查 #if 条件)时,就会出现真正的麻烦。

For example, in stddef.h in VS2005, there is:

例如,在VS2005的stddef.h中,有:

#ifdef  _WIN64
#define offsetof(s,m)   (size_t)( (ptrdiff_t)&(((s *)0)->m) )
#else
#define offsetof(s,m)   (size_t)&(((s *)0)->m)
#endif

Now the problem: If I have a custom header ("custom.h") that needs to be used with many compilers, including some older ones that don't provide offsetofin their system headers, I should write in my header:

现在的问题是:如果我有一个需要与许多编译器一起使用的自定义标头(“custom.h”),包括一些offsetof在其系统标头中未提供的旧编译器,我应该在我的标头中写入:

#ifndef offsetof
#define offsetof(s,m)   (size_t)&(((s *)0)->m)
#endif

And be sure to tell the user to #include "custom.h"afterall system headers, otherwise, the line of offsetofin stddef.h will assert a macro redefinition error.

并且一定要告诉用户#include "custom.h"所有系统头之后,否则,offsetofstddef.h 中的行会断言宏重定义错误。

We pray not to meet any more of such cases in our career.

我们祈祷在我们的职业生涯中不再遇到此类情况。