C++代码规范总结(部分)
下面内容总结(有的是直接复制概述,因为原文讲的比较严谨)于https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/
头文件
#include
的路径和顺序(每个类型之间要有空行)- 配套的头文件
- C语言系统文件
- C++标准库头文件
- 其他库的头文件
- 本项目的头文件
- 要有
#define
防护符 - 避免向前声明
- 10行以下用内联函数
作用域
- 禁止使用
using namespace ...;
- 大型项目要使用命名空间,以注释结尾
- 尽量将非成员函数放入命名空间,不要使用全局函数
- 最好初始化时声明
- 要在循环外声明类
- 尽量不要使用全局的静态变量、类,除非它们可以平凡地析构
- 构造函数中不得使用虚函数,
- 尽量不要使用隐式转换类型,单参数函数使用
explicit
关键字 int
、double
等类型建议使用传值、std::string
等类型建议使用传引用,尽量不要传指针- 基类最好是抽象类,且构造函数和析构函数必须声明为
protected
,最好不要继承具体类 - 只能用
struct
定义那些用于储存数据的被动对象. 其他情况应该使用class
- 组合优于继承,使用
public
继承 - 谨慎使用重载运算符,除非与直觉相同;禁止使用自定义字面量
- 必须将所有数据成员声明为
private
- 声明次序
public
protected
private
以下是每一个不同作用域的声明次序:- 类型和类型别名
- (仅适用于结构体),非静态数据成员
- 静态常量
- 工厂函数
- 构造函数和赋值运算符
- 析构函数
- 所有其他函数,包括静态和非静态函数,以及友元函数
- 其它数据成员,包括静态和非静态的
函数
- 行数超过40行在不影响程序逻辑的情况下要进行分割
- 只有在常规写法 (返回类型前置) 不便于书写或不便于阅读时使用返回类型后置语法
- 尽量不使用缺省函数参数,少数极端情况除外。尽可能改用函数重载
- 允许合理的使用友元类及友元函数
其它C++特性
- 尽量不使用 C++ 异常.
- 不要使用强制转换
- 除了写日志,尽量不要使用流
- 对于迭代器和其他模板对象使用前缀形式 (
++i
) 的自增, 自减运算符 - 任何可能的情况下都要使用
const
- 使用宏时要非常谨慎, 尽量以内联函数, 枚举和常量代替之
- 指针使用nullptr,字符使用
'\0'
,而不是0
字面量 - 尽可能用
sizeof(varname)
代替sizeof(type)
- 使用
auto
绕过繁琐的类型名称,但要可读性好 - 可以用列表初始化
- 使用预处理宏时要非常谨慎,下面是要使用宏时需要遵守的规则:
- 不要在头文件中使用宏
- 在马上要使用时才进行
#define
, 使用后要立即#undef
- 不要只是对已经存在的宏使用
#undef
,选择一个不会冲突的名称 - 不要试图使用展开后会导致 C++ 构造不稳定的宏, 不然也至少要附上文档说明其行为
- 不要用
##
处理函数,类和变量的名字
- 适当使用lambda表达式,当lambda将转移当前作用域时,首选显式捕捉
- 不要使用复杂的模板编程
命名约定
- 函数命名, 变量命名, 文件命名要有描述性; 少用缩写
- 文件名全部要小写,可以包含“
-
”或“_
” - 类型名称首字母要大写,不能有下划线
- 变量命名要全部小写,单词之间使用下划线
- 常规函数使用大小写混合
- 命名空间要小写,不可以出现缩写
- 枚举的命名应当和常量或宏一致
- 通常不应该使用宏. 如果不得不用, 其命名像枚举命名一样全部大写, 使用下划线
注释
- 在每一个文件开头加入版权公告,包含法律、版权、作者信息。应当对文件的内容做一个大致的说明, 同时说明各概念之间的联系。
- 每个类的定义都要附带一份注释, 描述类的功能和用法, 除非它的功能相当明显
- 函数声明处的注释描述函数功能; 定义处的注释描述函数实现
- 每个类数据成员 (也叫实例变量或成员变量) 都应该用注释说明用途,如果变量可以接受
NULL
或-1
等警戒值, 须加以说明 - 所有全局变量也要注释说明含义及用途, 以及作为全局变量的原因
- 对于代码中巧妙的, 晦涩的, 有趣的, 重要的地方加以注释
- 巧妙或复杂的代码段前要加注释
- 比较隐晦的地方要在行尾加入注释
- 永远不要 用自然语言翻译代码作为注释
- 对那些临时的, 短期的解决方案, 或已经够好但仍不完美的代码使用
TODO
注释,并加上自己身份标识
格式
- 每一行代码字符数不超过 80
- 尽量不使用非 ASCII 字符, 使用时必须使用 UTF-8 编码
- 只使用空格, 每次缩进 2 个空格
- 返回类型和函数名在同一行, 参数也尽量放在同一行, 如果放不下就对形参分行, 分行方式与 函数调用 一致
- 如果能增强可读性, 简短的条件语句允许写在同一行. 只有当语句简单并且没有使用
else
子句时使用 - 单行语句不需要使用大括号, 如果你喜欢用也没问题; 复杂的条件或循环语句用大括号可读性会更好. 也有一些项目要求
if
必须总是使用大括号 - 如果有不满足
case
条件的枚举值, switch 应该总是包含一个default
匹配,如果default
应该永远执行不到, 简单的加条assert
- 在单语句循环里, 括号可用可不用
- 空循环体应使用
{}
或continue
, 而不是一个简单的分号 - 句点或箭头前后不要有空格. 指针/地址操作符 (
*
,&
) 之后不能有空格 - 如果一个布尔表达式超过 标准行宽, 断行方式要统一一下
- 预处理指令不要缩进, 从行首开始
- 构造函数初始化列表放在同一行或按四格缩进并排多行
- 命名空间内容不缩进
- 两个函数定义之间的空行不要超过 2 行, 函数体首尾不要留空行, 函数体中也不要随意添加空行
规则特例
- 不要使用
#pragma once