编码规范是程序编码所要遵循的规则,要注意代码的正确性、稳定性、可读性。要避免使用不易理解的数字,用有意义的标识来替代,不要使用难懂的技巧性很高的语句。
规范的重要性
- 增加开发过程代码的强壮性、可读性、易维护性;减少有经验和无经验开发人员编程所需的脑力工作;
- 在项目范围内统一代码风格;
- 通过人为以及自动的方式对最终软件应用质量标准;
- 使新的开发人员快速适应项目氛围;
- 支持项目资源的复用:允许开发人员从一个项目区域(或子项目团队)移动到另一个,而不需要重新适应新的子项目团队的氛围。
最小混淆 - 它的生存期中,源代码的读远比写多,规约更是这样。理想情况下,源代码读起来应该象英语一样描述了所要做的事
维护的唯一点 - 只要可能,设计决策就应在源中只表述一点,它的多数后果应程序化的派生于此点。不遵守这一原则严重损害了可维护性、可靠性和可理解性。
最小干扰 - 避免将源代码与可视干扰(如内容较少或对理解软件目的不起作用的信息)相混合:
文件组成
- 类声明和实现分别放在不同的文件中(.h和.cpp)
- 模板类的实现和声明要放在同一个文件中(h)
- 除非是模板函数,所有的函数实现都不要放在class声明中,即使函数是inline函数
头文件的引用
- 为头文件加上重复包含的保护 (不要使用#pragma once)
- 公共头文件要保证自足性(不需要用户在引用时需要引用其他的文件)
- 只引用需要的文件
- <>只用在引用系统或语言本身提供的头文件,其他情况一律用””
- 引用头文件不要用绝对路径
- 不要在头文件中定义常量/变量
- 在源文件中不要用关键字extern
- 所有的#include 都要视为大小写敏感
命名原则:
- 公开的接口函数和全局名字空间的函数选择SmallTalk风格的命名原则(一种首字母大写,字间直接相连而无分隔符的书写风格)
- 私有的函数使用C++ 草拟标准工作底稿使用的约定(全部为小写字符、字间以下划线分隔)
- 避免使用只靠字母大小写才能区分的名称
- 宏要使用全大写的名称
- typedef定义的类型要使用大写字母的名称
- 指针类型的变量名使用p作为前缀
- 命名时避免以下划线开头,名称中避免出现两个下划线相连
- 如果某个单词没有标准的缩写,要使用全名
- 使用英语命名,尽量选用可以发音和有意义的名字
- 名字中不要出现形状容易混淆的字母和数字
- 类型能够表达的含义在变量中不要重复
- 类名和对象名要使用名词或名词短语
- 实现行为的过程或函数要使用动词或动词短语
- 表示存取和查询的函数使用名词或形容词短语
- 布尔型的名字要使用正值谓词从句
- 拷贝构造函数或操作符重载的左值参数使用lhs,右值参数使用rhs来命名
书写格式:
- 对嵌套语句使用4个字符的缩进
- 每一行不超过78个字符
- 单目操作符的前后不要加空格,双目和三元操作符前后一定要加空格
- “::”的前后不要加空格,“, ”和“;”的后面要加空格
- 用空行将代码按逻辑片断划分
- 函数的参数过长,要从第二个参数开始换行显示,每一个参数和第一个参数对齐
- 不要在一行中放多于一条的语句
- template<typename T……>独立占一行
- switch中每个case各占一行
- 为所有的switch提供default
- 定义指针和引用*和&紧跟类型
- 静态成员的访问用::而不使用.或-〉访问
注释
- 用英语写注释
- 尽量用代码自说明,而不是使用注释
- 使用C++风格的注释
- 注释不能超出被注释代码所包含的内容
- 不可以在注释中约束使用者的行为
- 将不再使用的代码删除而不是注释掉
- 每个空的循环体都需要给出确认性注释
- 若某个case不需要break需要加注释
声明:
- 类的操作按public, protected, private, friend 的顺序排列
- 成员函数按构造函数、析构函数,操作符和其他函数的顺序排列
- 显式的声明函数的返回值类型
- 用typedef代替define的类型别名定义
- 返回指针的函数用NULL表示失败
- 不要返回可写的成员变量的指针或引用
- 无法确定是否会被继承的类需要使用虚析构函数
- 带有指针类型成员变量的类需要声明拷贝构造函数和赋值操作符
- 赋值操作符需要做自赋值判断
- 不改变成员变量的成员函数需要定义成const
- 不要重新定义父类的非虚函数
- 不要把操作符重载成非习惯的行为
- 避免使用值传递对象
- 尽量使用默认参数,而不是重载
- 除非必要不使用无符号的内置类型
内存分配和释放
- 使用new delete 而不使用malloc calloc realloc 和free
- new delete 和new[],delete[]要成对使用
- 谁申请谁释放
- 自定义类的new操作符一定要自定义类的delete
- 内存指针释放后,指针应有一个合理的值
- 申明时初始化而不是使用前才初始化
类型转换
- 用显示方式进行类型转换而不使用单参数构造函数的隐式转换
- 不要直接比较bool型变量
- 不要对浮点类型作等于和不等于判断
- 在循环过程中不要修改循环计数器
宏
- 若宏值多于一项,一定要使用括号
- 用{}把宏函数括起来
- 不要在公共头文件中定义宏
异常
- 在确实是异常的时候才抛出异常
- 确保异常发生后资源还能被回收
- 捕捉异常时绝对不能先基类后派生类
- 捕捉异常要使用异常对象的引用
兼容性
- 遵守ANSIC和ISO C++的标准,将不符合国际标准的代码与其他代码分开
- 不要强制引用/指针指向尺寸不同的目标
- 任何通过数组下标索引的操作都要做溢出检查
- 不要假设函数参数的计算顺序
- 代码中用到路径只用/, 而不使用\
- 不要用移位操作代替乘除法
- 不要把NULL用在指针以外的场合
性能
- 不要在循环体内定义对象
- 使用 += , -=,〉>>=, 等复合运算符,而不使用 A = A+1…等这样的操作(减少临时对象)