Google c++ style guide notes

精简《Google C++ Style Guide》,只保留注意事项,以便工作期间随时翻阅。

1. 头文件

1.1 头文件要自给自足,即其他源文件包含该头文件后,无需额外引入其他头文件或依赖,就能使用该头文件中定义的类、函数或者宏。
1.2 使用 #define 来防止头文件被多重包含。
1.3 尽可能避免使用前置声明。使用 #include 包含需要的头文件即可。
1.4 只有当函数只有10 行甚至更少时才将其定义为内联函数。
1.5 使用标准的头文件包含顺序增强可读性,避免隐藏依赖。

  • 相关头文件
  • C 库
  • C++ 库
  • 其他库的头文件
  • 本项目内的其他头文件
    google-awesome-project/src/foo/internal/fooserver.cc的包含次序如下:
#include "foo/public/fooserver.h"

#include <sys/types.h>
#include <unistd.h>

#include <hash_map>
#include <vector>

#include "base/basictypes.h"
#include "base/commandlineflags.h"

#include "foo/public/bar.h"

2. 作用域

2.1 在.cc 文件内使用匿名命名空间,使用具名命名空间时,其名称可基于项目名或相对路径。禁止使用using指示(using-directive)。禁止使用内联命名空间(inline namespace)。

namespace { // 匿名命名空间
// 名字空间的内容无需缩进
enum { kUNUSED, kEOF, kERROR }; // 经常使用的符号
bool AtEof() { return pos_ == kEOF; } // 使用本名字空间内的符号EOF
} // namespace
namespace mynamespace {
// 具名命名空间
// 所有声明都置于命名空间中
// 注意不要使用缩进
class MyClass {
public:
…
void Foo();
};
} // namespace mynamespace

2.2 将嵌套类的声明置于命名空间内。
2.3 使用静态成员函数或命名空间内的非成员函数,不使用裸的全局函数。
2.4 将函数变量尽可能置于最小作用域内,并在变量声明时进行初始化。
2.5 禁止使用class类型的静态或全局变量。

3. 类

3.1 不在构造函数中进行复杂的初始化,尤其是那些有可能失败或者需要调用虚函数的初始化。
3.2 如果类中定义了成员变量, 则必须在类中为每个类提供初始化函数或定义一个构造函数。若未声明构造函数, 则
编译器会生成一个默认的构造函数,这有可能导致某些成员未被初始化或被初始化为不恰当的值。
3.3 对单个参数的构造函数使用C++关键字explicit。
3.4 如果你的类型需要,就让它们支持拷贝/移动,否则,就把隐式产生的拷贝和移动函数禁用。
3.5 在能够减少重复代码的情况下使用委派和继承构造函数。
3.6 仅当只有数据时使用struct,其它情况一律使用class。
3.7 使用组合常常比使用继承更合理,如果使用继承,定义为public继承。
3.8 用到多重继承的情况少之又少,只在以下情况使用多重继承:只有一个基类是非抽象类;其他基类都是以Interface为后缀的纯接口类。
3.9 接口是满足特定条件的类,以Interface为后缀。
3.10 除少数特定环境外,不要重载运算符。
3.11 在类中使用特定的声明顺序:public在private之前,函数在变量之前。

  • typedefs 和 enum
  • 常量
  • 构造函数
  • 析构函数
  • 函数
  • 变量

3.12 编写简短、凝练的函数。

4. 一些技巧

4.1 动态分配出的对象最好有单一且固定的所有主(owner),且通过智能指针传递所有权(ownership)。
4.2 使用cpplint.py检查代码风格,项目地址在这,cpplint.py。

当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。

5. 其他C++特性

5.1 所有按引用传递的参数必须加上const。
5.2 只在定义移动构造函数与移动赋值操作时使用右值引用,不要使用std::forward。
5.3 若使用函数重载,最好让代码阅读者一看调用点就胸有成竹,不用花心思猜测调用的重载函数到底是哪一种。该规则适用于构造函数。
5.4 不允许函数使用默认参数,少数极端情况除外。尽可能使用函数重载。
5.5 不允许使用变长数组和alloca()。
5.6 允许合理使用友元类及友元函数。
5.7 不使用C++异常。
5.8 禁止使用RTTI(Run Time Type Information)。
5.9 使用C++的类型转换,如static_cast<>()。不使用 int y = (int)x 或 int y = int(x) 等方式。
5.10 只在记录日志时使用流。
5.11 对于迭代器和其他模板对象使用前缀形式(++i)的自增自减运算符。

6. 命名约定

6.1 函数命名,变量命名,文件命名要有描述性,少用缩写。可接受的文件命名:my_useful_class.cc。
6.2 文件名全部小写,可包含下划线或连字符。如my_useful_class.cc。
6.3 类型名称(类、结构体、类型定义、枚举)的每个单词首字母均大写,不包含下划线。如MyUsefulClass。
6.4 变量名一律小写,单词间用下划线连接。如my_useful_class。
6.5 在全局或类里的常量名称前加k,除去开头的k之外,每个单词首字母大写。
6.6 常规函数大小写混合。如set_my_useful_class_variable()。
6.7 名字空间用小写字母命名,并基于项目名称和目录结构,如google_awesome_project。
6.8 枚举和常量、宏保持一致,优先选择常量风格。

7. 注释

7.1 注释风格保持统一。
7.2 文件注释,在每一个文件开头加入版权公告,然后是文件内容描述。
7.3 类注释,每个类的定义都要附带一份注释,描述类的功能和用法。
7.4 函数注释,函数声明处注释描述函数功能,定义处描述函数实现。
7.5 变量注释,通常变量名本身足以很好说明变量用途,某些情况下才需要额外的注释说明。
7.6 对代码中巧妙的、晦涩的、有趣的、重要的地方加以注释。
7.7 注意标点、拼写和语法。好的注释令代码更易读懂。
7.8 对那些临时的,短期的解决方案,或已经够好但仍不完美的代码使用TODO注释。
7.9 通过弃用注释(DEPRECATED comments)以标记某接口点(interface points)已弃用。

8. 格式

8.1 每一行代码字符数不超过80。
8.2 尽量使用ASCII字符,如果不够用,必须使用UTF-8编码。
8.3 只使用空格,每次缩进2个空格。
8.4 返回类型和函数名在同一行,参数也尽量放在同一行,如果放不下就对形参分行。
8.5 其它函数怎么格式化形参和函数体,Lambda表达式就怎么格式化,捕获列表同理。
8.6 要么一行写完函数调用,要么在圆括号里对参数分行,要么参数另起一行且缩进四格。如果没有其它顾虑的
话,尽可能精简行数。
8.7 列表初始化,与函数调用保持一致。
8.8 倾向于不在圆括号内使用空格,关键字if和else另起一行。
8.9 switch 语句可以使用大括号分段,以表明cases之间不是连在一起的。在单语句循环里,括号可用可不用。空循环体应使用{} 或continue。
8.10 句点或箭头前后不要出现空格。指针/地址操作符(*,&)之后不能有空格。
8.11 如果一个布尔表达式超过标准行宽,断行方式要统一。
8.12 return表达式里时没必要都用圆括号。
8.13 变量及数组初始化用=,(),{}均可。
8.14 预处理指令不要缩进,从行首开始。
8.15 访问控制块的声明次序是public、protected、private,每次缩进一个空格。
8.16 构造函数初始值列表放在同一行或按四格缩进并排几行。
8.17 命名空间内容不缩进。
8.18 水平留白的使用因地制宜,永远不要在行尾添加没意义的留白。
8.19 垂直留白越少越好。

猜你喜欢

转载自blog.csdn.net/qq_40773984/article/details/133025682