大型项目开发: 头文件顺序

原创 2015年07月09日 00:25:17

经验告诉我们,某些编码实践虽然在C++中完全合法,但是绝对不能应用于大型项目环境中。 大型项目环境下必须有适当的约束,否则很容易变得难以控制并很难维护(摘自<<大规模C++程序设计>>)。下面以Chromium中运用的两个Coding Style中定义的头文件顺序为例。

头文件顺序的差异

WebKit/Blink遵循业界标准的定义,其实也是Lakos在<<大规模C++程序设计>>中建议的顺序 :

  1. 编译单元对应的头文件 (Related header file)。
  2. 工程内的其它头文件。
  3. 库及系统头文件。

(Blink特殊的一点是编译单元必须先包含config.h。)

这样做的目的是为避免隐性依赖。每个头文件都应当做到自包含(Self-Contained, or Self Sufficient), 这样保证用户能直接头文件中理解它的物理依赖。如果遵循这个顺序,当出现隐性依赖时,是无法编译通过的。

下面这个例子:
my_class.h中依赖了std::string, 但没有显式的包含,当main里先包含标准库的头文件string时,编译是不会出错的。

main.cc

#include <string>
#include <iostream>
#include "my_class.h"

int main(int argc, char* argv[]) {
  MyClass aInstance;
  std::cout << aInstance.value() << std::endl;
}

my_class.h

#ifndef MY_CLASS_H_
#define MY_CLASS_H_
class MyClass {
 public:
  MyClass();
  const std::string& value();
 private:
  std::string value_;
};
#endif

如果遵循上面的规则,就会在编译main.cc时报错:
In file included from main.cc:1:
./my_class.h:6:9: error: use of undeclared identifier 'std'
  const std::string& value();

在一个层次更为清晰的项目下,错误最好归属到作者身上。这里main.cc做为my_class.h的用户,这样的错误最好由my_class.h的作者来解决。所以Google定义了如下的规则:
关联的头文件
C库头文件
C++库头文件
其它库头文件
* 项目中的其它头文件。
实现如下的my_class.cc时就会收到报错:
my_class.cc
#include "my_class.h"
#include <string>


MyClass::MyClass()
  :value_("Hello!") {
}

在这种情况下,这个错误将只报给my_class.h对应的编译单元my_class.cc。
In file included from my_class.cc:1:
./my_class.h:6:9: error: use of undeclared identifier 'std'
  const std::string& value();

如果是一个小项目,可能察觉不到这样做的差异。但在讲求职责清晰,分工协作的大型项目下,它就会变得很有价值。
这是一个很小的点,可见大型项目中一些规则定义的冰山一角。再比如大型项目中的头文件还有一些设计上的权衡。比如避免不必要包含头文件会拖慢项目的构建效率,引入了前置声明。但它却在一些场景下会造成歧义(比如前置声明标准库中的类,或者模板类),或者引入一些的维护成本和风险(比如函数的参数变化,需要对应修改前置声明)。Google早期是鼓励使用前置声明,而现在只是强调在明确带来好处的情况下才建议使用前置声明。

扩展阅读:

Self-sufficient header files in C/C++
Headers and Includes: Why and How
C/C++ include file order/best practices

C++头文件的包含顺序研究

作者:朱金灿来源:http://blog.csdn.net/clever101 一.《Google C++ 编程风格指南》里的观点      公司在推行编码规范,领导提议基本上使用《Google C+...

头文件包含顺序以及设计原则

关于C的头文件包含,我认为体现了软件的模块设计以及包含关系,对于头文件包含,我个人看法如下: 1. 一个基础头文件提供常用的数据类型、修饰符以及基础操作宏。例如叫basicdef.h 2. 头文件...

头文件包含顺序处理方法

关于enum声明的变量被其他文件(.h或.c)引用到时,由于头文件包含顺序引起的error的处理办法:   根据整个系统架构划分出应用层(APP),中间层(RTE),服务层(service)以及底层...

MTD/MT/MDD/MD以及LIB/DLL之间的一些联系和问题

下面来说下MTD/MT/MDD/MD以及LIB/DLL之间的一些联系和问题: 一 动态库DLL  静态库LIB MSVC中工程只有三种类型,即LIB库,...

正式宣布DXBC2GLSL,HLSL字节码到GLSL的编译器

转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=2826 三年前,我就曾经计划过一个KlayGE的长期研发子项目,D3D11 HL...

大型项目的struts,spring配置文件

  • 2011年12月31日 15:31
  • 24KB
  • 下载

【Flask】在PyCharm上组织Flask大型项目文件结构

要想用Flask开发大型项目,就必须要有良好的项目文件结构,这篇文章主要记录Flask最小开发项目的配置。这里所使用的Python版本为3.5.1,Flask版本为0.11.1。...

Flask 大型项目开发教程

  • 2017年11月17日 16:52
  • 557KB
  • 下载

精益开发实战(用看板管理大型项目)读后感

精彩内容,稍后继续。。。
  • shehun1
  • shehun1
  • 2013年06月30日 23:05
  • 2522
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:大型项目开发: 头文件顺序
举报原因:
原因补充:

(最多只允许输入30个字)