编码规范补充
1. 头文件
1.1. include guard
所有头文件都应该使用#define 防止头文件被多重包含。
为保证唯一性,头文件的命名应基于其所在项目源代码树的全路径。例如,项目foo 中的头文件foo/src/bar/baz.h 按如下方式保护:
#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_
...
#endif // FOO_BAR_BAZ_H_
1.2. 尽量使用 forward declaration
使用前向声明(forward declarations),尽量减少.h 文件中#include 的数量。
当一个头文件被包含的同时也引入了一项新的依赖,只要该头文件被修改,代码就要重新编译。使用前置声明可以显著减少需要包含的头文件数量。
举例说明:头文件中用到类File,但不需要访问File 的声明,则头文件中只需前置声明class File;无需
#include"file/base/file.h"
namespace 中的 class 都可以前向声明,模板也可以前向声明,例如 class Foo; typedef std::shared_ptr<Foo> FooPtr。但是 nested class 无法前向声明。
1.3. 头文件包含顺序
保证每个构成interface的头文件都独立可用,xxx.cpp 文件第一个包含的头文件应该是 xxx.h。
cpp 文件和头文件中写 include 时按一定的原则分组(例如本项目、本公司、第三方C++库、C++标准库、第三方C库),每组以内按字母顺序排列头文件。
cpp 文件中的头文件有以下两种常用包含顺序:
-
《Google C++ Style Guide》推荐顺序:(对xxx.cpp)
- xxx.h
- C 系统文件
- C++ 系统文件
- 其他库的 .h 文件
- 本项目内 .h 文件
-
《C++编程思想》推荐顺序:(对xxx.cpp)
- xxx.h
- 本项目内 .h 文件
- 其他库的 .h 文件
- C++ 系统文件
- C 系统文件
两者相同的地方是将xxx.h 放在开始,避免隐藏依赖
第一种的优点:符合从一般到特殊的顺序,比较容易理解。
第二种的优点:符合从特殊到一般的顺序,能够暴露出自己的头文件是不是包含了所有必需的系统文件。如果某个自己的头文件没有包含必需的系统文件的话,会导致编译错误。建议使用第二种包含顺序。
2.变量命名
1. 匈牙利命名法的缺点
(1)一些版本的匈牙利约定事实上忽视了用抽象数据类型作为基本类型。它们以程序语言中整型、长整型、浮点数和字符串为基础来建立基本类型。
(2)匈牙利约定基本类型事实上是没有什么价值的,因为它使得程序员陷入对类型进行人工检查的困扰之中,而不是让编译程序对类型进行更加快速而又准确的检查。这种形式匈牙利约定的另一个问题是它把数据的意义与其表现联系在一起。比如,说明某一变量是整型的,把它改为长整型的时,不得不改动这一变量的名称。
(3)匈牙利约定的最后一个问题是它鼓励了懒惰、不含什么信息的变量名的出现。当程序员用hwnd 来命名对窗口的操作时,往往忽视了他所指的到底是哪种窗口、对话框、菜单还是帮助区的屏幕?显然用 hwndmenu 要比 hwnd 清楚得多。以变量的意义为代价来获得对其类型的精确描述显然是愚蠢的。不过好在可以用加限定词的办法来同时获得完整的意义和精确的类型。