C++ 风格指南
- 此文章目的是精简 Google 风格指南(C++ 版),只列出“你要怎么做,哪些情况下可以不这么做”。
- 如果要详细了解“为什么要这么做,以及如何权衡其利弊”,请阅读 0. 扉页 中的项目主页。
个人或团队未必要完全遵照指南亦步亦趋。可以参照该指南,或从中汲取灵感,建立适合自身实际情况的规范。
0. 扉页
-
版本:4.45
-
原作者:
Benjy Weinberger
Craig Silverstein
Gregory Eitzmann
Mark Mentovai
Tashana Landray
1. 头文件
- 通常每一个
.cc
文件都有一个对应的.h
文件。 - 例外:单元测试代码和只包含
main()
函数的.cc
文件。
1.1. Self-contained 头文件
- 头文件应自给自足(self-contained,可以作为第一个头文件被引入),并以
.h
结尾。 - 头文件要有 1.2. #define保护 保护,包含所需要的其它头文件,也不要求定义任何特别符号(symbols)。
- 文本插入文件并非自给自足,应以
.inc
结尾。不允许分离出-inl.h
头文件的做法。 - 在同一个
.h
文件中声明和定义模板或内联函数。不要把这些定义放到分离的-inl.h
文件里。 - 例外:函数模板为所有相关模板参数显式实例化,或是某类的一个私有成员,那么它就只能定义在实例化该模板的
.cc
文件里。
1.2. #define 保护
- 头文件应该使用
#define
,来防止头文件被多重包含。 - 命名格式当是:
<PROJECT>_<PATH>_<FILE>_H_
,基于所在项目源代码树的全路径。
项目 foo
中的头文件 foo/src/bar/baz.h
可按如下方式保护:
#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_
...
#endif // FOO_BAR_BAZ_H_
1.3. 前置声明
- 尽量避免前置声明那些定义在其他项目中的实体。
- 函数:总是使用
#include
。 - 类模板:优先使用
#include
。 - 包含头文件的时机,参见 1.5. #include 的路径及顺序 。
1.4. 内联函数
- 鼓励使用内联,但不要内联超过 10 行的函数。
- 谨慎对待析构函数。
- 内联那些包含循环或 switch 语句的函数常常是得不偿失的。
- 虚函数和递归函数不会被正常内联,递归函数不应该声明成内联函数。
1.5. #include
的路径及顺序
- 项目内头文件应按照项目源代码目录树结构排列。
- 避免使用 UNIX 特殊的快捷目录
.
(当前目录) 或..
(上级目录)。
例如,google-awesome-project/src/base/logging.h
应该按如下方式包含:
#include "base/logging.h"
又如,dir/foo.cc
中,包含头文件的次序如下:
dir2/foo2.h
「相关头文件」(优先位置, 详情如下)- C 库
- C++ 库
- 其他库的
.h
- 本项目内的
.h
举例来说,google-awesome-project/src/foo/internal/fooserver.cc
的包含次序如下:
#include "foo/public/fooserver.h" // 优先位置
#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"
- 在
#include
中插入空行以分割相关头文件 .cc
和.h
通常位于同一目录下,但也可以放在不同目录下。- 可以字母顺序分别对每种类型的头文件进行二次排序。
- 所依赖的符号(symbols)被哪些头文件所定义,就应该包含(include)哪些头文件,前置声明(forward declarations)情况除外.除非
.h
有明确说明会自动提供其中的symbol。 - 凡是
.cc
文件所对应的「相关头文件」已经包含的,就不用再重复包含进其 cc 文件里面了。 - 例外:需要条件编译(conditional includes)平台特定(system-specific)放到其它 includes 之后。如:
#include "foo/public/fooserver.h"
#include "base/port.h" // For LANG_CXX11.
#ifdef LANG_CXX11
#include <initializer_list>
#endif // LANG_CXX11