自己整理的Google公司C++版编码规范

编码规范

目录

编码规范... 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

 

 

 

1. 头文件

1.1. #define 保护

        #ifndef FOO_BAR_BAZ_H_

        #define FOO_BAR_BAZ_H_

        ...

        #endif // FOO_BAR_BAZ_H_

1.2. 前置声明

        尽可能地避免使用前置声明。使用 ``#include`` 包含需要的头文件即可。

1.3. 内联函数

        只有当函数只有 10 行甚至更少时才将其定义为内联函数.

1.4. ``#include`` 的路径及顺序

项目内头文件应按照项目源代码目录树结构排列, 避免使用 UNIX 特殊的快捷目录 ``.`` (当前目录) 或 ``..`` (上级目录)

假设``dir/foo.cc`` 或 ``dir/foo_test.cc`` 的主要作用是实现或测试 ``dir2/foo2.h`` 的功能, ``foo.cc`` 中包含头文件的次序如下:

        #. ``dir2/foo2.h`` (优先位置, 详情如下)

        #. C 系统文件

        #. C++ 系统文件

        #. 其他库的 ``.h`` 文件

#. 本项目内 ``.h`` 文件

 

2. 作用域

2.1. 命名空间

        鼓励在 ``.cc`` 文件内使用匿名命名空间或 ``static`` 声明.

2.2. 匿名命名空间和静态变量

        在 ``.cc`` 文件中定义一个不需要被外部引用的变量时,可以将它们放在匿名命名空间或声明为 ``static`` 。但是不要在 ``.h`` 文件中这么做。

2.3. 非成员函数、静态成员函数和全局函数

        使用静态成员函数或命名空间内的非成员函数, 尽量不要用裸的全局函数. 将一系列函数直接置于命名空间中,不要用类的静态方法模拟出命名空间的效果,类的静态方法应当和类的实例或静态数据紧密相关.

2.4. 局部变量

        将函数变量尽可能置于最小作用域内, 并在变量声明时进行初始化.

C++ 允许在函数的任何位置声明变量. 我们提倡在尽可能小的作用域中声明变量, 离第一次使用越近越好. 这使得代码浏览者更容易定位变量声明的位置, 了解变量的类型和初始值.

2.5. 静态和全局变量

多线程中的全局变量 (含静态成员变量) 不要使用 ``class`` 类型 (含 STL 容器), 避免不明确行为导致的 bug.

 

3. 类

3.1. 构造函数的职责

不要在构造函数中调用虚函数, 也不要在无法报出错误时进行可能失败的初始化.

3.2. 隐式类型转换

不要定义隐式类型转换. 对于转换运算符和单参数构造函数, 请使用 ``explicit`` 关键字.

3.3. 可拷贝类型和可赋值类型

如果你的类型需要, 就让它们支持拷贝 / 赋值. 否则, 就把隐式产生的拷贝和赋值函数禁用.

显式地通过在 ``public`` 域中使用 ``= delete`` 或其他手段禁用之.

        MyClass(const MyClass&) = delete;

MyClass& operator=(const MyClass&) = delete;

 

3.4. 结构体 VS. 类

仅当只有数据成员时使用 ``struct``, 其它一概使用 ``class``.

如果需要更多的函数功能, ``class`` 更适合. 如果拿不准, 就用 ``class``.

3.5. 运算符重载

除少数特定环境外, 不要重载运算符. 也不要创建用户定义字面量.

3.6. 存取控制

将 *所有* 数据成员声明为 ``private``, 除非是 ``static const`` 类型成员

3.7. 声明顺序

类定义一般应以 ``public:`` 开始, 后跟 ``protected:``, 最后是 ``private:``. 省略空部分.

在各个部分中, 建议将类似的声明放在一起, 并且建议以如下的顺序: 类型 (包括 ``typedef``, ``using`` 和嵌套的结构体与类), 常量, 工厂函数, 构造函数, 赋值运算符, 析构函数, 其它函数, 数据成员.

不要将大段的函数定义内联在类定义中. 通常,只有那些普通的, 或性能关键且短小的函数可以内联在类定义中.

 

4. 函数

4.1. 参数顺序

函数的参数顺序为: 输入参数在先, 后跟输出参数.

4.2. 编写简短函数

如果函数超过 40 行, 可以思索一下能不能在不影响程序结构的前提下对其进行分割.

4.3. 缺省参数

只允许在非虚函数中使用缺省参数, 且必须保证缺省参数的值始终一致.

不要写像 ``void f(int n = counter++);`` 这样的代码.

 

5. 命名约定

5.1. 通用命名规则

函数命名, 变量命名, 文件命名要有描述性; 少用缩写.

尽可能使用描述性的命名, 别心疼空间, 毕竟相比之下让代码易于新读者理解更重要. 不要用只有项目开发者能理解的缩写, 也不要通过砍掉几个字母来缩写单词.

例子:

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;              // 删减了若干字母.

 

5.2. 文件命名

文件名要全部小写, 可以包含下划线 (``_``)

例子:``my_useful_class.cc``

5.3. 类型命名

类型名称的每个单词首字母均大写, 不包含下划线: ``MyExcitingClass``, ``MyExcitingEnum``.

5.4. 变量命名

        程序中涉及到需要用的专业性词汇,统一使用附录中对应的单词进行变量名命名

5.5. 函数命名

常规函数使用大小写混合, 取值和设值函数则要求与变量名匹配: ``MyExcitingFunction()``, ``MyExcitingMethod()``, ``my_exciting_member_variable()``, ``set_my_exciting_member_variable()``.

 

6. 格式

6.1. 行长度

每一行代码字符数尽量不超过 80.

6.2. 非 ASCII 字符

尽量不使用非 ASCII 字符, 使用时必须使用 UTF-8 编码. 十六进制编码也可以。

6.3. 空格还是制表位

只使用空格, 每次缩进 4 个空格.

6.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();

 

7 注释

7.1.文件头注释

  参考格式:

/*

* @Author: xxxx

* @Date:   2019-5-5 13:59:14

* @brief:  

* @Last Modified by:   xxxx

* @Last Modified time: 2019-5-5 13:59:27

*/

7.2.函数注释

 1) 关键函数必须写上注释,说明函数的用途。

 2) 特别函数参数,需要说明参数的目的,由谁负责释放等等。

 3) 除了特别情况,注释写在代码之前,不要放到代码行之后。

 4) 对每个#else或#endif给出行末注释。

 5) 关键代码注释,包括但不限于:赋值,函数调用,表达式,分支等等。

 6) 善未实现完整的代码,或者需要进一步优化的代码,应加上 // TODO …

 7) 调试的代码,加上注释 // only for DEBUG

 8) 需要引起关注的代码,加上注释 // NOTE …

 9) 对于较大的代码块结尾,如for,while,do等,可加上 // end for|while|do

 

附录

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

猜你喜欢

转载自blog.csdn.net/wei375653972/article/details/89844013