C++ 编程风格

@Ta 05-10 16:03 392点击

参考《Google C++ 编程风格指南》 整理

头文件

  • 建议:每一个.cpp文件都要对应一个.h头文件
  • 头文件必须使用#define保护,统一包含它所需要的其它头文件,也不要求定义任何特别符号,不要使用 #pragma once
  • #define保护的命名格式为<PROJECT>_<PATH>_<FILE>_H_
  • 建议:尽量避免使用前置声明,使用#include包含需要的头文件即可
  • 只有当函数只有10行甚至更少时才将其定义为内联函数
  • include顺序
  1. 首选头文件
  2. C 系统文件
  3. C++ 系统文件
  4. 其他库的 .h 文件
  5. 本项目内 .h 文件

作用域

  • 禁止使用 using 指示(using-directive)
  • 禁止使用内联命名空间(inline namespace)
  • 禁止在命名空间 std 内声明
  • 禁止在头文件中使用命名空间别名
  • 在命名空间的最后注释出命名空间的名字
  • 命名空间中声明和定义不要使用缩进
  • 匿名命名空间的声明和命名空间的格式相同,在最后注释上 namespace,所有置于匿名命名空间的声明都具有内部链接性
  • 建议:非成员函数应尽量置于某个命名空间内或静态非成员函数
  • 建议:尽可能小的作用域中声明变量, 离第一次使用越近越好,并在变量声明时初始化
  • 建议:循环语句内的变量尽量在外部声明
  • 全局变量,静态变量,静态类成员变量和函数静态变量,都必须是原生数据类型, 以及 POD 类型的指针、数组和结构体。

  • 禁止在构造函数中调用虚函数

  • 禁止在无法报出错误时进行可能失败的初始化,考虑使用 Init() 方法或使用工厂模式

  • 禁止在构造函数中抛出异常

  • 不要定义隐式类型转换

  • 如果需要就让你的类型可拷贝, 需要同时给出拷贝构造函数和赋值操作符的定义

  • 类型不需要拷贝, 需要将拷贝构造函数和赋值运算符禁用。

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

  • 所有继承必须是 public

  • 如果基类有虚函数, 则析构函数也应该为虚函数

  • 所有数据成员都是私有的

  • 只有当所有父类除第一个外都是 <a href="#3.7. 接口">纯接口类</a> 时, 才允许使用多重继承

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

  • 建议:类中声明顺序为类型 (包括 typedef, using 和嵌套的结构体与类), 常量, 工厂函数, 构造函数, 赋值运算符, 析构函数, 其它函数, 数据成员

函数

  • 建议:函数的参数顺序为: 输入参数在先, 后跟输出参数
  • 输入参数通常是值参或 const 引用, 输出参数或输入/输出参数则一般为非 const 指针
  • 输出参数禁止使用引用
  • 建议:函数尽量简短
  • 引用参数必须是const
  • 输入参数使用const指针,需要说明原因
  • 禁止虚函数使用缺省参数
  • 指针检查

其他c++特性

  • 我们自己的代码中不要抛出异常,但是需要抓取第三方库的异常。捕获的异常需要处理,错误异常要输出日志
  • 除了项目中第三方库需要,我们禁止使用 RTTI
  • 不要使用流, 除非是日志接口需要. 使用 printf 之类的代替
  • 统一使用前置自增 (自减)
  • 强烈建议你在任何可能的情况下都要使用
  • 使用<stdint.h>中长度精确的整形
  • 只在一个文件中使用的宏要在.cc文件中定义不要定义在头文件中
  • 指针变量定义时要初始化,指针销毁后要置nullptr,指针使用前要进行有效性判断
  • 指针使用前要使用if (nullptr == p)if (nullptr == p)进行防错处理
  • 指针初始化用nullptr
  • sizeof(varname)代替sizeof(type)
  • 禁止使用复杂的模板编程,参数不要超过3个.
  • 不要使用C++11,除非项目中第三方库需要

命名约定

  • 命名要有一致性
  • 文件名要全部小写, 可以包含下划线,对于MFC项目中自动生成的文件名可不遵循本规则
  • 类, 结构体, 类型定义 (typedef), 枚举命名单词首字母均大写, 不包含下划线
    命名规则 类型+描述
    类型
    C :类
    Struct : 结构体
    P : typedef/using 指针类型
    En: 枚举
  • 变量命名采用匈牙利命名法
  • 函数命名采用帕斯卡命名法
  • const变量用const前缀
  • 命名空间命名全部小写,嵌套命名空间要注意冲突
  • 枚举类型使用En前缀,枚举值命名全大写ENUM前缀
  • _宏命名全大写下划线_分割

注释

  • 文件头,函数/类说明使用/ /*
  • 其他使用 // 或 `/ */`, 统一就好
  • 每个文件开头加入文件注释,包括版权、说明、作者等信息,文件注释应当对文件的内容做一个大致的说明, 同时说明各概念之间的联系
  • 每个类的定义都要附带一份注释, 描述类的功能和用法,如果该类的实例可被多线程访问, 要特别注意文档说明多线程环境下相关的规则和常量使用,用一小段代码演示这个类的基本用法或通常用法
  • 类的声明和定义分开了(例如分别放在了 .h.cc 文件中), 此时, 描述类用法的注释应当和接口定义放在一起, 描述类的操作和实现的注释应当和实现放在一起
  • 函数的注释声明处描述函数功能; 定义处的注释描述函数实现;函数声明处注释函数的输入输出,参数是否可以为空等,函数定义处主要注释函数如何实现
  • 变量注释,变量名不足以说明用途,如果变量可以接受 NULL-1 等警戒值, 须加以说明;全局变量注释全局的原因
  • 复杂代码前添加注释,行注释空2格
  • TODO注释用来临时的, 短期的解决方案, 或已经够好但仍不完美的代码,为了在 \"将来某一天做某事。格式使用全大写的字符串 TODO, 在随后的圆括号里写上你的名字, 邮件地址, bug ID
  • 弃用注释标记某接口为弃用状态,格式全大写的 DEPRECATED 在括号中留下您的名字, 邮箱地址以及其他身份标识
  • 修改他人注释格式//name 日期,修改原因

格式

  • 建议:每一行代码字符数不超过 80
  • 只使用空格, 每次缩进 2 个空格
  • 函数返回值和函数名保持同一行,形参放不下可以分行
  • 函数调用要么在圆括号里对参数分行, 要么参数另起一行且缩进四格
  • 条件语句中不要在圆括号内使用空格. 关键字 ifelse 另起一行,如果有else if 在最后要加一个 else
  • 开关语句中case语句使用大括号,应该总是包含一个 default 匹配,如果 default 应该永远执行不到, 简单的加条 assert ,两条case之间没有break需要注释加以说明
  • 句点或箭头前后不要有空格. 指针/地址操作符 (*, &) 之后不能有空格
  • 声明指针变量或参数时, 星号与变量名紧挨
  • ==与常量比较时常量要写在前面
  • 布尔表达式中逻辑与 (&&) 操作符总位于行头
  • 只有在写 x = expr 要加上括号的时候才在 return expr; 里使用括号
  • 禁用 std::initializer_list 构造函数
  • 预处理指令不要缩进, 从行首开始,即使预处理指令位于缩进代码块中, 指令也应从行首开始
  • 访问控制块的声明依次序是 public:, protected:, private:, 不缩进
  • 命名空间内容不缩进
  • 不要使用 #pragma once
回复列表(0)
帖子没有回复
添加新回复
回复需要登录

[聊天-公共聊天室] 方哥:@寻梦xunm,鸡佬,捏好!小尾巴华为Mate30 X Max基佬版