Featured image of post C++ 代码规范总结

C++ 代码规范总结

对谷歌代码规范的总结

C++代码规范总结(部分)

下面内容总结(有的是直接复制概述,因为原文讲的比较严谨)于https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/

头文件

  • #include的路径和顺序(每个类型之间要有空行)
    • 配套的头文件
    • C语言系统文件
    • C++标准库头文件
    • 其他库的头文件
    • 本项目的头文件
  • 要有#define防护符
  • 避免向前声明
  • 10行以下用内联函数

作用域

  • 禁止使用using namespace ...;
  • 大型项目要使用命名空间,以注释结尾
  • 尽量将非成员函数放入命名空间,不要使用全局函数
  • 最好初始化时声明
  • 要在循环外声明类
  • 尽量不要使用全局的静态变量、类,除非它们可以平凡地析构
  • 构造函数中不得使用虚函数,
  • 尽量不要使用隐式转换类型,单参数函数使用explicit关键字
  • intdouble等类型建议使用传值、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
Licensed under CC BY-NC-SA 4.0