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

发表于:2016-10-31 09:21

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:朱金灿    来源:51Testing软件测试网采编

  一.《Google C++ 编程风格指南》里的观点
  公司在推行编码规范,领导提议基本上使用《Google C++ 编程风格指南》。其中《Google C++ 编程风格指南》对于头文件的包含顺序是这样的:
  Names and Order of Includes
  link ▽Use standard order for readability and to avoid hidden dependencies:C library, C++ library, other libraries’ .h, your project’s .h.
  All of a project’s header files should belisted as descendants of the project’s source directory without use of UNIXdirectory shortcuts . (the current directory) or .. (the parent directory). Forexample, google-awesome-project/src/base/logging.h should be included as
  #include “base/logging.h”
  In dir/foo.cc or dir/foo_test.cc, whosemain purpose is to implement or test the stuff in dir2/foo2.h, order yourincludes as follows:
  dir2/foo2.h (preferred location — seedetails below).
  C system files.
  C++ system files.
  Other libraries’ .h files.
  Your project’s .h files.
  The preferred ordering reduces hiddendependencies. We want every header file to be compilable on its own. Theeasiest way to achieve this is to make sure that every one of them is the first.h file #included in some .cc.
  dir/foo.cc and dir2/foo2.h are often in thesame directory (e.g. base/basictypes_test.cc and base/basictypes.h), but can bein different directories too.
  Within each section it is nice to order theincludes alphabetically.
  For example, the includes ingoogle-awesome-project/src/foo/internal/fooserver.cc might look like this:
#include "foo/public/fooserver.h"  // Preferred location.
#include <sys/types.h>
#include <unistd.h>
#include <hash_map>
#include <vector>
#include "base/basictypes.h"
#include"base/commandlineflags.h"
#include "foo/public/bar.h"
  在这里我谈一下我对上面的理解(如不当,还请诸位同学指正):
  1.      为了加强可读性和避免隐含依赖,应使用下面的顺序:C标准库、C++标准库、其它库的头文件、你自己工程的头文件。不过这里最先包含的是首选的头文件,即例如a.cpp文件中应该优先包含a.h。首选的头文件是为了减少隐藏依赖,同时确保头文件和实现文件是匹配的。具体的例子是:假如你有一个cc文件(linux平台的cpp文件后缀为cc)是google-awesome-project/src/foo/internal/fooserver.cc,那么它所包含的头文件的顺序如下:
  #include <sys/types.h>
  #include <unistd.h>
  #include <hash_map>
  #include <vector>
  #include "base/basictypes.h"
  #include "base/commandlineflags.h"
  #include "foo/public/bar.h"
  2. 在包含头文件时应该加上头文件所在工程的文件夹名,即假如你有这样一个工程base,里面有一个logging.h,那么外部包含这个头文件应该这样写:
  #include “base/logging.h”,而不是#include “logging.h”
  我们看到的是这里《Google C++ 编程风格指南》倡导的原则背后隐藏的目的是:
  1. 为了减少隐藏依赖,同时头文件和其实现文件匹配,应该先包含其首选项(即其对应的头文件)。
  2. 除了首选项外,遵循的是从一般到特殊的原则。不过我觉得《Google C++ 编程风格指南》的顺序:C标准库、C++标准库、其它库的头文件、你自己工程的头文件中漏了最前面的一项:操作系统级别的头文件,比如上面的例子sys/types.h估计不能归入C标准库,而是Linux操作系统提供的SDK吧。因此我觉得更准确的说法应该是:OS SDK .h , C标准库、C++标准库、其它库的头文件、你自己工程的头文件。
  3.之所以要将头文件所在的工程目录列出,作用应该是命名空间是一样的,就是为了区分不小心造成的文件重名。
  二.《C++编程思想》中的不同观点
  与《Google C++ 编程风格指南》不同的是,《C++编程思想》倡导一种不同的规则。《C++编程思想》P432提到:
  头文件被包含的顺序是从“最特殊到最一般”。这就是,在本地目录的任何头文件首先被包含。然后是我们自己的所有“工具”头文件,随后是第三方库头文件,接着是标准C++库头文件和C库头文件。
  要了解其原因:可以看JohnLakos在《Large ScaleC++ Softwre Design》(注:其中文译名为《大规模C++程序设计》)中的一段话:
  保证.h文件的组成部分不被它自身解析(parse),这可以避免潜在的使用错误。因为被自身解析缺乏明确提供的声明或定义。在.c文件的第一行包含.h 文件能确保所有对于构件的物理界面重要的内部信息块都在.h中(如果的确是缺少了某些信息块,一旦编译这个.c文件时就可以发现这个问题)。
  如果包含头文件的顺序是“从最特殊到最一般”,如果我们的头文件不被它自己解析。我们将马上找到它,防止麻烦事情发生。
21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号