Google C++ 风格指南 - 中文版¶
版本:
3.133
Benjy Weinberger
Craig Silverstein
原作者:
Gregory Eitzmann
Mark Mentovai
Tashana Landray
翻译:
YuleFox
yospaly
项目主页:
Google Style Guide
Google 开源项目风格指南 - 中文版
Arranged By Corsair
Google C++ 风格指南 - 中文版
1
目录
Google C++ 风格指南 - 中文版¶ .................................................1
译者前言¶ .................................................................... 1
背景¶ ........................................................................ 1
1. 头文件¶ ................................................................... 3
1.1. #define 保护¶ ....................................................... 3
1.2. 头文件依赖¶ ......................................................... 3
1.3. 内联函数¶ ........................................................... 3
1.4. -inl.h 文件¶ .........................................................4
1.5. 函数参数的顺序¶ ..................................................... 4
1.6. #include 的路径及顺序¶ .............................................. 5
译者 (YuleFox) 笔记¶ ..................................................... 5
2. 作用域¶ ................................................................... 7
2.1. 名字空间¶ ........................................................... 7
2.1.1. 匿名名字空间¶ ................................................. 7
2.1.2. 具名的名字空间¶ ............................................... 7
2.2. 嵌套类¶ ............................................................. 9
2.3. 非成员函数, 静态成员函数, 和全局函数¶ ............................... 9
2.4. 局部变量¶ .......................................................... 10
2.5. 静态和全局变量¶ .................................................... 10
译者 (YuleFox) 笔记¶ .................................................... 11
3. 类¶ ...................................................................... 12
3.1. 构造函数的职责¶ .................................................... 12
3.2. 默认构造函数¶ ...................................................... 12
3.3. 显式构造函数¶ ...................................................... 13
3.4. 拷贝构造函数¶ ...................................................... 13
3.5. 结构体 VS. 类¶ ..................................................... 15
3.6. 继承¶ .............................................................. 15
3.7. 多重继承¶ .......................................................... 17
3.8. 接口¶ .............................................................. 17
3.9. 运算符重载¶ ........................................................ 18
3.10. 存取控制¶ ......................................................... 18
3.11. 声明顺序¶ ......................................................... 19
3.12. 编写简短函数¶ ..................................................... 19
译者 (YuleFox) 笔记¶ .................................................... 19
4. 来自 Google 的奇技¶ ...................................................... 21
4.1. 智能指针¶ .......................................................... 21
4.2. cpplint¶ ........................................................... 21
5. 其他 C++ 特性¶ ........................................................... 22
5.1. 引用参数¶ .......................................................... 22
5.2. 函数重载¶ .......................................................... 22
5.3. 缺省参数¶ .......................................................... 23
5.4. 变长数组和 alloca()¶ ............................................... 23
5.5. 友元¶ .............................................................. 23
5.6. 异常¶ .............................................................. 24
5.7. 运行时类型识别¶ .................................................... 25
5.8. 类型转换¶ .......................................................... 25
Google C++ 风格指南 - 中文版
2
5.9. 流¶ ................................................................ 26
5.10. 前置自增和自减¶ ................................................... 27
5.11. const 的使用¶ ..................................................... 28
5.12. 整型¶ ............................................................. 28
5.13. 64 位下的可移植性¶ ................................................ 29
5.14. 预处理宏¶ ......................................................... 30
5.15. 0 和 NULL¶ ........................................................ 31
5.16. sizeof¶ ........................................................... 31
5.17. Boost 库¶ ......................................................... 31
6. 命名约定¶ ................................................................ 33
6.1. 通用命名规则¶ ...................................................... 33
6.2. 文件命名¶ .......................................................... 34
6.3. 类型命名¶ .......................................................... 34
6.4. 变量命名¶ .......................................................... 34
6.5. 常量命名¶ .......................................................... 36
6.6. 函数命名¶ .......................................................... 36
6.7. 名字空间命名¶ ...................................................... 36
6.8. 枚举命名¶ .......................................................... 36
6.9. 宏命名¶ ............................................................ 37
6.10. 命名规则的特例¶ ................................................... 37
7. 注释¶ .................................................................... 38
7.1. 注释风格¶ .......................................................... 38
7.2. 文件注释¶ .......................................................... 38
7.3. 类注释¶ ............................................................ 38
7.4. 函数注释¶ .......................................................... 39
7.5. 变量注释¶ .......................................................... 40
7.6. 实现注释¶ .......................................................... 40
7.7. 标点, 拼写和语法¶ .................................................. 41
7.8. TODO 注释¶ ......................................................... 42
译者 (YuleFox) 笔记¶ .................................................... 42
8. 格式¶ .................................................................... 43
8.1. 行长度¶ ............................................................ 43
8.2. 非 ASCII 字符¶ ..................................................... 43
8.3. 空格还是制表位¶ .................................................... 43
8.4. 函数声明与定义¶ .................................................... 44
8.5. 函数调用¶ .......................................................... 46
8.6. 条件语句¶ .......................................................... 47
8.7. 循环和开关选择语句¶ ................................................ 48
8.8. 指针和引用表达式¶ .................................................. 49
8.9. 布尔表达式¶ ........................................................ 49
8.10. 函数返回值¶ ....................................................... 50
8.11. 变量及数组初始化¶ ................................................. 50
8.12. 预处理指令¶ ....................................................... 50
8.13. 类格式¶ ........................................................... 50
8.14. 初始化列表¶ ....................................................... 51
8.15. 名字空间格式化¶ ................................................... 51
8.16. 水平留白¶ ......................................................... 52
8.17. 垂直留白¶ ......................................................... 53
译者 (YuleFox) 笔记¶ .................................................... 54
9. 规则特例¶ ................................................................ 56
9.1. 现有不合规范的代码¶ ................................................ 56
9.2. Windows 代码¶ ...................................................... 56
10. 结束语¶ ................................................................. 58
Google C++ 风格指南 - 中文版
3
Google C++ 风格指南 - 中文版
1
译者前言¶
Google 经常会发布一些开源项目, 意味着会接受来自其他代码贡献者的代码. 但是如果代
码贡献者的编程风格与 Google 的不一致, 会给代码阅读者和其他代码提交这造成不小的困
扰. Google 因此发布了这份自己的编程风格, 使所有提交代码的人都能获知 Google 的编程
风格.
翻译初衷:
规则的作用就是避免混乱. 但规则本身一定要权威, 有说服力, 并且是理性的. 我们所
见过的大部分编程规范, 其内容或不够严谨, 或阐述过于简单, 或带有一定的武断性.
Google 保持其一贯的严谨精神, 5 万汉字的指南涉及广泛, 论证严密. 我们翻译该系列
指南的主因也正是其严谨性. 严谨意味着指南的价值不仅仅局限于它罗列出的规范, 更
具参考意义的是它为了列出规范而做的谨慎权衡过程.
指南不仅列出你要怎么做, 还告诉你为什么要这么做, 哪些情况下可以不这么做, 以及
如何权衡其利弊. 其他团队未必要完全遵照指南亦步亦趋, 如前面所说, 这份指南是
Google 根据自身实际情况打造的, 适用于其主导的开源项目. 其他团队可以参照该指
南, 或从中汲取灵感, 建立适合自身实际情况的规范.
我们在翻译的过程中, 收获颇多. 希望本系列指南中文版对你同样能有所帮助.
我们翻译时也是尽力保持严谨, 但水平所限, bug 在所难免. 有任何意见或建议, 可与我们
取得联系.
中文版和英文版一样, 使用 Artistic License/GPL 开源许可.
中文版修订历史:
2009-06 3.133 : YuleFox 的 1.0 版已经相当完善, 但原版在近一年的时间里, 其
规范也发生了一些变化.
yospaly 与 YuleFox 一拍即合, 以项目的形式来延续中文版 : Google
开源项目风格指南 - 中文版项目.
主要变化是同步到 3.133 最新英文版本, 做部分勘误和改善可读性方面
的修改, 并改进排版效果. yospaly 重新翻修, YuleFox 做后续评审.
2008-07 1.0 : 出自 YuleFox 的 Blog, 很多地方摘录的也是该版本.
背景¶
C++ 是 Google 大部分开源项目的主要编程语言. 正如每个 C++ 程序员都知道的, C++ 有很
多强大的特性, 但这种强大不可避免的导致它走向复杂,使代码更容易产生 bug, 难以阅读
和维护.
本指南的目的是通过详细阐述 C++ 注意事项来驾驭其复杂性. 这些规则在保证代码易于管
理的同时, 高效使用 C++ 的语言特性.
风格, 亦被称作可读性, 也就是指导 C++ 编程的约定. 使用术语 “风格” 有些用词不当,
因为这些习惯远不止源代码文件格式化这么简单.
使代码易于管理的方法之一是加强代码一致性. 让任何程序员都可以快速读懂你的代码这点
非常重要. 保持统一编程风格并遵守约定意味着可以很容易根据 “模式匹配” 规则来推断
Google C++ 风格指南 - 中文版
2
各种标识符的含义. 创建通用, 必需的习惯用语和模式可以使代码更容易理解. 在一些情况
下可能有充分的理由改变某些编程风格, 但我们还是应该遵循一致性原则,尽量不这么做.
本指南的另一个观点是 C++ 特性的臃肿. C++ 是一门包含大量高级特性的庞大语言. 某些情
况下, 我们会限制甚至禁止使用某些特性. 这么做是为了保持代码清爽, 避免这些特性可能
导致的各种问题. 指南中列举了这类特性, 并解释为什么这些特性被限制使用.
Google 主导的开源项目均符合本指南的规定.
注意: 本指南并非 C++ 教程, 我们假定读者已经对 C++ 非常熟悉.
Google C++ 风格指南 - 中文版
3
1. 头文件¶
通常每一个 .cc 文件都有一个对应的 .h 文件. 也有一些常见例外, 如单元测试代码和只
包含 main() 函数的 .cc 文件.
正确使用头文件可令代码在可读性、文件大小和性能上大为改观.
下面的规则将引导你规避使用头文件时的各种陷阱.
1.1. #define 保护¶
Tip
所有头文件都应该使用 #define 防止头文件被多重包含, 命名格式当是:
___H_
为保证唯一性, 头文件的命名应该依据所在项目源代码树的全路径. 例如, 项目 foo 中的
头文件 foo/src/bar/baz.h 可按如下方式保护:
#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_
…
#endif // FOO_BAR_BAZ_H_
1.2. 头文件依赖¶
Tip
能用前置声明的地方尽量不使用 #include.
当一个头文件被包含的同时也引入了新的依赖, 一旦该头文件被修改, 代码就会被重新编译.
如果这个头文件又包含了其他头文件, 这些头文件的任何改变都将导致所有包含了该头文件
的代码被重新编译. 因此, 我们倾向于减少包含头文件, 尤其是在头文件中包含头文件.
使用前置声明可以显著减少需要包含的头文件数量. 举例说明: 如果头文件中用到类 File,
但不需要访问 File 类的声明, 头文件中只需前置声明 class File; 而无须 #include
"file/base/file.h".
不允许访问类的定义的前提下, 我们在一个头文件中能对类 Foo 做哪些操作?
我们可以将数据成员类型声明为 Foo * 或 Foo &.
我们可以将函数参数 / 返回值的类型声明为 Foo (但不能定义实现).
我们可以将静态数据成员的类型声明为 Foo, 因为静态数据成员的定义在类定义之
外.
反之, 如果你的类是 Foo 的子类, 或者含有类型为 Foo 的非静态数据成员, 则必须包含
Foo 所在的头文件.
有时, 使用指针成员 (如果是 scoped_ptr 更好) 替代对象成员的确是明智之选. 然而, 这
会降低代码可读性及执行效率, 因此如果仅仅为了少包含头文件,还是不要这么做的好.
当然 .cc 文件无论如何都需要所使用类的定义部分, 自然也就会包含若干头文件.
1.3. 内联函数¶
Tip
Google C++ 风格指南 - 中文版
4
只有当函数只有 10 行甚至更少时才将其定义为内联函数.
定义:
当函数被声明为内联函数之后, 编译器会将其内联展开, 而不是按通常的函数调用机制
进行调用.
优点:
当函数体比较小的时候, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它
函数体比较短, 性能关键的函数, 鼓励使用内联.
缺点:
滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小.
内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增
加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行更快。
结论:
一个较为合理的经验准则是, 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函
数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用!
另一个实用的经验准则: 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除
非在大多数情况下, 这些循环或 switch 语句从不被执行).
有些函数即使声明为内联的也不一定会被编译器内联, 这点很重要; 比如虚函数和递归
函数就不会被正常内联. 通常, 递归函数不应该声明成内联函数.(YuleFox 注: 递归调
用堆栈的展开并不像循环那么简单, 比如递归层数在编译时可能是未知的, 大多数编译
器都不支持内联递归函数). 虚函数内联的主要原因则是想把它的函数体放在类定义内,
为了图个方便, 抑或是当作文档描述其行为, 比如精短的存取函数.
1.4. -inl.h 文件¶
Tip
复杂的内联函数的定义, 应放在后缀名为 -inl.h 的头文件中.
内联函数的定义必须放在头文件中, 编译器才能在调用点内联展开定义. 然而, 实现代码理
论上应该放在 .cc 文件中, 我们不希望 .h 文件中有太多实现代码, 除非在可读性和性能
上有明显优势.
如果内联函数的定义比较短小, 逻辑比较简单, 实现代码放在 .h 文件里没有任何问题. 比
如, 存取函数的实现理所当然都应该放在类定义内. 出于编写者和调用者的方便, 较复杂的
内联函数也可以放到 .h 文件中, 如果你觉得这样会使头文件显得笨重, 也可以把它萃取到
单独的 -inl.h 中. 这样把实现和类定义分离开来, 当需要时包含对应的 -inl.h 即可。
-inl.h 文件还可用于函数模板的定义. 从而增强模板定义的可读性.
别忘了 -inl.h 和其他头文件一样, 也需要 #define 保护.
1.5. 函数参数的顺序¶
Tip
定义函数时, 参数顺序依次为: 输入参数, 然后是输出参数.
C/C++ 函数参数分为输入参数, 输出参数, 和输入/输出参数三种. 输入参数一般传值或传
const 引用, 输出参数或输入/输出参数则是非-const 指针. 对参数排序时, 将只输入的参
数放在所有输出参数之前. 尤其是不要仅仅因为是新加的参数, 就把它放在最后; 即使是新
加的只输入参数也要放在输出参数.