原文转自: http://www.tanjp.com (即时修正和更新)
前言
使代码易于管理的方法之一是加强代码一致性。让任何程序员都可以快速读懂你的代码这点非常重要。保持统一编程风格并遵守约定意味着可以很容易根据“模式匹配”规则来推断各种标识符的含义.。创建通用,必需的习惯用语和模式可以使代码更容易理解。在一些情况下可能有充分的理由改变某些编程风格,但我们还是应该遵循一致性原则,尽量不这么做。
本指南的另一个观点是 C++ 特性的臃肿。C++ 是一门包含大量高级特性的庞大语言。某些情况下,我们会限制甚至禁止使用某些特性。这么做是为了保持代码清爽,避免这些特性可能导致的各种问题。指南中列举了这类特性,并解释为什么这些特性被限制使用。
1 头文件
通常每一个 .cpp 文件都有一个对应的 .h 文件,也有一些常见例外,如单元测试代码和只包含 main() 函数的 .cpp 文件。
正确使用头文件可令代码在可读性、文件大小和性能上大为改观。
下面的规则将引导你规避使用头文件时的各种陷阱。
1.1 自给自足
头文件应该能够自给自足(也就是可以作为第一个头文件被引入),以 .h 结尾。至于用来插入文本的文件,说到底它们并不是头文件,所以应以 .inc 结尾。不允许分离出 -inl.h 头文件的做法。
如果 .h 文件声明了一个模板或内联函数,同时也在该文件加以定义。凡是有用到这些的 .cpp 文件,就得统统包含该头文件,否则程序可能会在构建中链接失败。不要把这些定义放到分离的 -inl.h 文件里。
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
1.3 不使用前置声明
尽可能地避免使用前置声明。使用 #include 包含需要的头文件即可。
定义:所谓「前置声明」(forward declaration)是类、函数和模板的纯粹声明,没伴随着其定义.
优点:前置声明能够节省编译时间,多余的 #include 会迫使编译器展开更多的文件,处理更多的输入。
缺点:
1> 前置声明隐藏了依赖关系,头文件改动时,用户的代码会跳过必要的重新编译过程。
2> 前置声明可能会被库的后续更改所破坏。前置声明函数或模板有时会妨碍头文件开发者变动其 API. 例如扩大形参类型,加个自带默认参数的模板形参等等。
3> 前置声明来自命名空间 std:: 的 symbol 时,其行为未定义。
4> 前置声明了不少来自头文件的 symbol 时,就会比单单一行的 include 冗长。
1.4 内联函数要精简
只有当函数少于10行时才将其定义为内联函数。虚函数和递归函数不使用内联。
1.5 #include 的路径及顺序
include路径中不使用相对路径 ./ 和 ../
头文件包含次序如下(每组之间用空行隔开):
1> 当前 .cpp 对应的 .h 文件
2> C系统文件
3> C++系统文件
4> 其他库的 .h 文件
5> 本项目内的 .h 文件
举例来说,project/src/foo/internal/fooserver.cpp 的包含次序如下:
<