应该以什么顺序指定包含文件,即包含一个头文件在另一个头文件之前的原因是什么?
例如,系统文件、STL和Boost是在本地包含文件之前还是之后?
应该以什么顺序指定包含文件,即包含一个头文件在另一个头文件之前的原因是什么?
例如,系统文件、STL和Boost是在本地包含文件之前还是之后?
当前回答
要记住的一件重要的事情是,您的头文件不应该依赖于首先包含的其他头文件。确保这一点的一种方法是在任何其他头文件之前包含您的头文件。
《c++思维》特别提到了这一点,引用了Lakos的《大规模c++软件设计》:
可以通过确保组件的.h文件自己进行解析来避免潜在的使用错误——没有外部提供的声明或定义……将.h文件作为.c文件的第一行,可以确保.h文件中不缺少组件物理接口固有的关键信息(或者,如果有的话,在尝试编译.c文件时就会发现它)。
也就是说,按以下顺序包括:
这个实现的原型/接口头文件(即.h/。对应于.cpp/. Hh文件。cc文件)。 同一项目中的其他头文件,视需要而定。 来自其他非标准、非系统库(例如Qt、Eigen等)的头文件。 来自其他“几乎标准”库的头文件(例如,Boost) 标准c++头文件(例如iostream, functional等) 标准C头文件(例如,cstdint, direct .h等)
如果任何标题在这个顺序中有问题,要么修复它们(如果你的),要么就不要使用它们。抵制不编写干净头文件的库。
谷歌的c++风格指南几乎完全相反,没有任何正当理由;我个人倾向于Lakos方法。
其他回答
这不是主观的。确保你的头文件不依赖于以特定顺序被#包含。可以肯定的是,不管你以什么顺序包含STL或Boost头文件。
从最特定到最不特定,如果存在.cpp,则从对应的.hpp开始。这样,头文件中任何不是自给自足的隐藏依赖关系都将被显示出来。
由于使用了预编译的头文件,这变得更加复杂。解决这个问题的一种方法是,在不特定于项目编译器的情况下,使用一个项目头作为预编译的头包含文件。
要记住的一件重要的事情是,您的头文件不应该依赖于首先包含的其他头文件。确保这一点的一种方法是在任何其他头文件之前包含您的头文件。
《c++思维》特别提到了这一点,引用了Lakos的《大规模c++软件设计》:
可以通过确保组件的.h文件自己进行解析来避免潜在的使用错误——没有外部提供的声明或定义……将.h文件作为.c文件的第一行,可以确保.h文件中不缺少组件物理接口固有的关键信息(或者,如果有的话,在尝试编译.c文件时就会发现它)。
也就是说,按以下顺序包括:
这个实现的原型/接口头文件(即.h/。对应于.cpp/. Hh文件。cc文件)。 同一项目中的其他头文件,视需要而定。 来自其他非标准、非系统库(例如Qt、Eigen等)的头文件。 来自其他“几乎标准”库的头文件(例如,Boost) 标准c++头文件(例如iostream, functional等) 标准C头文件(例如,cstdint, direct .h等)
如果任何标题在这个顺序中有问题,要么修复它们(如果你的),要么就不要使用它们。抵制不编写干净头文件的库。
谷歌的c++风格指南几乎完全相反,没有任何正当理由;我个人倾向于Lakos方法。
在C/ c++世界中,这是一个很难回答的问题,因为有太多超出标准的元素。
我认为头文件的顺序不是一个严重的问题,只要它编译,就像squelart说的。
我的想法是:如果所有这些标题中的符号没有冲突,任何顺序都是OK的,并且标题依赖问题可以在以后通过在有缺陷的.h中添加#include行来修复。
真正的麻烦出现在某些头文件根据上面的头文件改变其操作(通过检查#if条件)时。
例如,在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
现在的问题是:如果我有一个自定义头文件("custom.h"),需要与许多编译器一起使用,包括一些在系统头文件中不提供偏移量的旧编译器,我应该在我的头文件中写道:
#ifndef offsetof
#define offsetof(s,m) (size_t)&(((s *)0)->m)
#endif
并且一定要告诉用户在所有系统头文件之后#include "custom.h",否则,stddef.h中的offset行将断言一个宏重定义错误。
我们祈祷在我们的职业生涯中不再遇到这种情况。
给自己添砖加瓦。
每个头文件都需要是自给自足的,只有当它至少被首次包含一次时,才能对其进行测试 不应该通过引入符号(宏、类型等)来错误地修改第三方标头的含义。
所以我通常是这样的:
// 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"
每组之间用空行分隔:
第一个对应于此cpp文件的头(健全性检查) 系统头文件 第三方头文件,按依赖顺序组织 项目标题 项目私有头文件
还要注意,除了系统头文件外,每个文件都位于一个与其名称空间同名的文件夹中,因为这样更容易跟踪它们。