对比华为命名规范和谷歌的差别
项目 | 子项 | 华为 | 谷歌 |
---|---|---|---|
命名 | |||
文件命名 | 大驼峰风格(DatabaseConnection.h) | 全小写,使用下划线或(-)连接(database_connection.h) | |
类型命名 | 所有类型使用大驼峰(UrlTableProperties) | 类型名每个单词首字母大写 | |
变量命名 | 以小驼峰为基础,三种风格:fileName, m_fileName, fileName_; | 变量、成员变量小写,成员变量以下划线结尾:file_name, file_name_ | |
常量命名 | 局部const 变量小驼峰;全局const变量大写。 | 命名时以 “k” 开头, 大小写混合使用; 如const int kDaysInAWeek = 7; | |
函数命名 | 动宾结构;大驼峰; | 常规函数使用大小写混合, 取值和设值函数则要求与变量名匹配: MyExcitingFunction() , my_exciting_member_variable() , set_my_exciting_member_variable() | |
命名空间 | 大驼峰 | 小写字母 | |
枚举 | 全大写,下划线链接;enum Color {RED, BLACK}; | 枚举的命名应当和 常量 或 宏 一致: kEnumName 或是 ENUM_NAME . | |
宏 | 全大写,下划线链接; | 通常 不应该 使用宏. 如果不得不用, 其命名像枚举命名一样全部大写, 使用下划线 | |
其他 | |||
头文件 | 头文件内容 | 头文件自包含;禁止包含用不到的头文件,禁止循环依赖 | 头文件应该能够自给自足(self-contained,也就是可以作为第一个头文件被引入),以 .h 结尾。至于用来插入文本的文件,说到底它们并不是头文件,所以应以 .inc 结尾。不允许分离出 -inl.h 头文件的做法. |
头文件使用#define保护 | 不要使用#pragma once; 保护符使用唯一标识名称。 | 为保证唯一性, 头文件的命名应该基于所在项目源代码树的全路径. 格式当是: <PROJECT>_<PATH>_<FILE>_H_ . | |
头文件包含顺序 | 首先是本cpp对应头文件,其他头文件建议按稳定顺序排序。 | 相关头文件, C 库, C++ 库, 其他库的 .h, 本项目内的 .h. | |
函数 | |||
参数顺序 | 建议:函数的参数顺序为: 输入参数在先, 后跟输出参数. | ||
引用参数 | 引用参数必须要加上const | ||
函数重载 | 函数重载, 则必须能让读者一看调用点就胸有成竹, 而不用花心思猜测调用的重载函数到底是哪一种. | ||
参数个数 | 参数个数不超过5个 | ||
类 | 构造函数 | 禁止在构造函数里面调用虚函数;成员变量必须显示初始化 | 不要在构造函数中调用虚函数, 也不要在无法报出错误时进行可能失败的初始化. |
析构函数 | 禁止在析构函数里面调用虚函数 | ||
隐式类型转换 | 单个参数的构造函数显式声明为explicit | 不要定义隐式类型转换. 对于转换运算符和单参数构造函数, 请使用 explicit 关键字. | |
拷贝/移动语义 | 拷贝构造/拷贝赋值;移动构造/移动赋值应该成对出现或禁止 | 如果你的类型需要, 就让它们支持拷贝 / 移动. 否则, 就把隐式产生的拷贝和移动函数禁用. | |
继承 | 基类析构函数必须声明为virtual; 禁止重定义非继承而来的飞虚函数;重写虚函数的时候加上override | 除了左边的几条,另外还有优先使用组合而非继承 | |
运算符重载 | 重载操作符要有充分的理由,而且不应该改变原来的语义 | 除少数特定环境外, 不要重载运算符. 也不要创建用户定义字面量. | |
作用域 | 命名空间 | 对于不需要导出的变量、常量、函数,使用匿名namespace或者static装饰; | 不要在头文件中使用 命名空间别名 除非显式标记内部命名空间使用。因为任何在头文件中引入的命名空间都会成为公开API的一部分;禁止使用内联命名空间 |
静态变量和全局变量 | (1)禁止定义静态储存周期非POD变量,禁止使用含有副作用的函数初始化POD全局变量,因为多编译单元中的静态变量执行时的构造和析构顺序是未明确的,这将导致代码的不可移植。(2)如果您确实需要一个 class 类型的静态或全局变量,可以考虑在 main() 函数或 pthread_once() 内初始化一个指针且永不回收。注意只能用 raw 指针,别用智能指针,毕竟后者的析构函数涉及到上文指出的不定顺序问题。 | ||
静态成员函数 | 使用静态成员函数或命名空间内的非成员函数, 尽量不要用裸的全局函数. 将一系列函数直接置于命名空间中,不要用类的静态方法模拟出命名空间的效果,类的静态方法应当和类的实例或静态数据紧密相关. | 优先使用命名空间来管理全局函数,除非和某个class有关系可以用静态成员函数 | |
局部变量 | 函数变量尽可能置于尽可能小的作用于,需要的时候再声明; | ||
注释 | |||
文件注释 | 每个文件头加上版权声明 | 文件头注释必须包含版权以及功能说明 | |
类注释 | 每个类的定义都要附带一份注释, 描述类的功能和用法, 除非它的功能相当明显. | ||
函数注释 | 函数声明处的注释描述函数功能; 定义处的注释描述函数实现. | ||
变量注释 | 通常变量名本身足以很好说明变量用途. 某些情况下, 也需要额外的注释说明,放在变量的上面说明 | ||
全局变量注释 | 和数据成员一样, 所有全局变量也要注释说明含义及用途, 以及作为全局变量的原因. 比如: | ||
算法注释 | 对于代码中巧妙的, 晦涩的, 有趣的, 重要的地方加以注释. | ||
TODO/FIXME | TODO/FIXME 注释要使用全大写的字符串 , 在随后的圆括号里写上你的名字或缩写; |