编码规范
目录
编码规范... 1
1. 头文件... 2
1.1. #define 保护... 2
1.2. 前置声明... 2
1.3. 内联函数... 2
1.4. ``#include`` 的路径及顺序... 2
2. 作用域... 3
2.1. 命名空间... 3
2.2. 匿名命名空间和静态变量... 3
2.3. 非成员函数、静态成员函数和全局函数... 3
2.4. 局部变量... 3
2.5. 静态和全局变量... 3
3. 类... 3
3.1. 构造函数的职责... 3
3.2. 隐式类型转换... 4
3.3. 可拷贝类型和可赋值类型... 4
3.4. 结构体 VS. 类... 4
3.5. 运算符重载... 4
3.6. 存取控制... 4
3.7. 声明顺序... 4
4. 函数... 5
4.1. 参数顺序... 5
4.2. 编写简短函数... 5
4.3. 缺省参数... 5
5. 命名约定... 5
5.1. 通用命名规则... 5
5.2. 文件命名... 6
5.3. 类型命名... 6
5.4. 变量命名... 6
5.5. 函数命名... 6
6. 格式... 6
6.1. 行长度... 6
6.2. 非 ASCII 字符... 6
6.3. 空格还是制表位... 6
6.4. 条件语句... 7
7 注释... 7
7.1.文件头注释... 7
7.2.函数注释... 7
附录... 9
#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_
...
#endif // FOO_BAR_BAZ_H_
尽可能地避免使用前置声明。使用 ``#include`` 包含需要的头文件即可。
只有当函数只有 10 行甚至更少时才将其定义为内联函数.
项目内头文件应按照项目源代码目录树结构排列, 避免使用 UNIX 特殊的快捷目录 ``.`` (当前目录) 或 ``..`` (上级目录)
假设``dir/foo.cc`` 或 ``dir/foo_test.cc`` 的主要作用是实现或测试 ``dir2/foo2.h`` 的功能, ``foo.cc`` 中包含头文件的次序如下:
#. ``dir2/foo2.h`` (优先位置, 详情如下)
#. C 系统文件
#. C++ 系统文件
#. 其他库的 ``.h`` 文件
#. 本项目内 ``.h`` 文件
鼓励在 ``.cc`` 文件内使用匿名命名空间或 ``static`` 声明.
在 ``.cc`` 文件中定义一个不需要被外部引用的变量时,可以将它们放在匿名命名空间或声明为 ``static`` 。但是不要在 ``.h`` 文件中这么做。
使用静态成员函数或命名空间内的非成员函数, 尽量不要用裸的全局函数. 将一系列函数直接置于命名空间中,不要用类的静态方法模拟出命名空间的效果,类的静态方法应当和类的实例或静态数据紧密相关.
将函数变量尽可能置于最小作用域内, 并在变量声明时进行初始化.
C++ 允许在函数的任何位置声明变量. 我们提倡在尽可能小的作用域中声明变量, 离第一次使用越近越好. 这使得代码浏览者更容易定位变量声明的位置, 了解变量的类型和初始值.
多线程中的全局变量 (含静态成员变量) 不要使用 ``class`` 类型 (含 STL 容器), 避免不明确行为导致的 bug.
不要在构造函数中调用虚函数, 也不要在无法报出错误时进行可能失败的初始化.
不要定义隐式类型转换. 对于转换运算符和单参数构造函数, 请使用 ``explicit`` 关键字.
如果你的类型需要, 就让它们支持拷贝 / 赋值. 否则, 就把隐式产生的拷贝和赋值函数禁用.
显式地通过在 ``public`` 域中使用 ``= delete`` 或其他手段禁用之.
MyClass(const MyClass&) = delete;
MyClass& operator=(const MyClass&) = delete;
仅当只有数据成员时使用 ``struct``, 其它一概使用 ``class``.
如果需要更多的函数功能, ``class`` 更适合. 如果拿不准, 就用 ``class``.
除少数特定环境外, 不要重载运算符. 也不要创建用户定义字面量.
将 *所有* 数据成员声明为 ``private``, 除非是 ``static const`` 类型成员
类定义一般应以 ``public:`` 开始, 后跟 ``protected:``, 最后是 ``private:``. 省略空部分.
在各个部分中, 建议将类似的声明放在一起, 并且建议以如下的顺序: 类型 (包括 ``typedef``, ``using`` 和嵌套的结构体与类), 常量, 工厂函数, 构造函数, 赋值运算符, 析构函数, 其它函数, 数据成员.
不要将大段的函数定义内联在类定义中. 通常,只有那些普通的, 或性能关键且短小的函数可以内联在类定义中.
函数的参数顺序为: 输入参数在先, 后跟输出参数.
如果函数超过 40 行, 可以思索一下能不能在不影响程序结构的前提下对其进行分割.
只允许在非虚函数中使用缺省参数, 且必须保证缺省参数的值始终一致.
不要写像 ``void f(int n = counter++);`` 这样的代码.
函数命名, 变量命名, 文件命名要有描述性; 少用缩写.
尽可能使用描述性的命名, 别心疼空间, 毕竟相比之下让代码易于新读者理解更重要. 不要用只有项目开发者能理解的缩写, 也不要通过砍掉几个字母来缩写单词.
例子:
int price_count_reader; // 无缩写
int num_errors; // "num" 是一个常见的写法
int num_dns_connections; // 人人都知道 "DNS" 是什么
int n; // 毫无意义.
int nerr; // 含糊不清的缩写.
int n_comp_conns; // 含糊不清的缩写.
int wgc_connections; // 只有贵团队知道是什么意思.
int pc_reader; // "pc" 有太多可能的解释了.
int cstmr_id; // 删减了若干字母.
文件名要全部小写, 可以包含下划线 (``_``)
例子:``my_useful_class.cc``
类型名称的每个单词首字母均大写, 不包含下划线: ``MyExcitingClass``, ``MyExcitingEnum``.
程序中涉及到需要用的专业性词汇,统一使用附录中对应的单词进行变量名命名
常规函数使用大小写混合, 取值和设值函数则要求与变量名匹配: ``MyExcitingFunction()``, ``MyExcitingMethod()``, ``my_exciting_member_variable()``, ``set_my_exciting_member_variable()``.
每一行代码字符数尽量不超过 80.
尽量不使用非 ASCII 字符, 使用时必须使用 UTF-8 编码. 十六进制编码也可以。
只使用空格, 每次缩进 4 个空格.
不在圆括号内使用空格. 关键字 ``if`` 和 ``else`` 另起一行.
if (condition) { // 圆括号里没有空格.
... // 2 空格缩进.
} else if (...) { // else 与 if 的右括号同一行.
...
} else {
...
}
if(condition) // 差 - IF 后面没空格.
if (condition){ // 差 - { 前面没空格.
if(condition){ // 变本加厉地差.
// 允许:
if (x == kFoo) return new Foo();
if (x == kBar) return new Bar();
// 不允许 - 当有 ELSE 分支时 IF 块却写在同一行
if (x) DoThis();
else DoThat();
参考格式:
/*
* @Author: xxxx
* @Date: 2019-5-5 13:59:14
* @brief:
* @Last Modified by: xxxx
* @Last Modified time: 2019-5-5 13:59:27
*/
1) 关键函数必须写上注释,说明函数的用途。
2) 特别函数参数,需要说明参数的目的,由谁负责释放等等。
3) 除了特别情况,注释写在代码之前,不要放到代码行之后。
4) 对每个#else或#endif给出行末注释。
5) 关键代码注释,包括但不限于:赋值,函数调用,表达式,分支等等。
6) 善未实现完整的代码,或者需要进一步优化的代码,应加上 // TODO …
7) 调试的代码,加上注释 // only for DEBUG
8) 需要引起关注的代码,加上注释 // NOTE …
9) 对于较大的代码块结尾,如for,while,do等,可加上 // end for|while|do
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|