头文件
先系统头文件,后用户头文件。
系统头文件应用:#include <xxx.h>
自定义同文件应用:#include "xxx.h"
h与cpp文件
头文件命名为.h,内联文件命名为.inl;C++文件命名为*.cpp
文件名用大小写混合,或者小写混合。例如DiyMainview.cpp,infoview.cpp。
头文件除了特殊情况,应使用#ifdef控制块。
头文件#endif应采用行尾注释。
头文件,首先是包含代码块,其次是宏定义代码块,然后是全局变量,全局常量,类型定义,类定义,内联部分。
CPP文件,包含指令,宏定义,全局变量,函数定义。
文件应包含文件头注释和内容。函数体类体之间原则上用2个空行。
注释方面
1. 文件头注释:作者,文件名称,文件说明,生成日期(可选)
2. 函数注释
关键函数必须写上注释,说明函数的用途。
特别函数参数,需要说明参数的目的,由谁负责释放等等。
除了特别情况,注释写在代码之前,不要放到代码行之后。
对每个#else或#endif给出行末注释。
关键代码注释,包括但不限于:赋值,函数调用,表达式,分支等等。
善未实现完整的代码,或者需要进一步优化的代码,应加上 // TODO …
调试的代码,加上注释 // only for DEBUG
需要引起关注的代码,加上注释 // NOTE …
对于较大的代码块结尾,如for,while,do等,可加上 // end for|while|do
命名方面
函数参数用a作为前缀。
循环变量和简单变量采用简单小写字符串即可。例如,int i;
指针变量用p打头,例如void* pBuffer;
全局变量加前缀 g_(表示 global)。静态变量加前缀 s_(表示 static)。类的成员变量加前缀 m_(表示 member),类的静态成员变量加前缀ms_
结构体、宏、枚举名、联合名全部大写,枚举名加小写前缀"enum",宏名加小写前缀"def"
常量全用大写的字母,用下划线分割单词
代码风格方面
类,结构,枚举,联合:大括号另起一行
"if"、"for"、"while"、"do"、"try"、"catch" 等语句自占一行,执行语句不得紧跟其后。不论执行语句有多少都要加 “{ }” 。这样可以防止书写和修改代码时出现失误。
"if"、"for"、"while"、"do"、"try"、"catch" 的括号和表达式,括号可紧挨关键字,这样强调的是表达式。
if语句如果有else语句,用 } else { 编写为一行,不推荐用 3 行代码的方式。
case关键字应和switch对齐。为所有switch语句提供default分支。若某个case不需要break一定要加注释声明。
空循环可用 for( ;; ) 或者 while( 1 ) 或者 while( true )
重载基类虚函数,应在该组虚函数前写注释 // implement XXX。友元声明放到类的末尾。
类型
定义指针和引用时*和&紧跟类型。
尽量避免使用浮点数,除非必须。
用typedef简化程序中的复杂语法。
少用union,如果一定要用,则采用简单数据类型成员。
用enum取代(一组相关的)常量。
不要使用魔鬼数字。
尽量用引用取代指针。
定义变量完成后立即初始化,勿等到使用时才进行。
如果有更优雅的解决方案,不要使用强制类型转换。
在同一块中按照 结构体和枚举-常量-构造函数-析构函数-成员函数-成员变量 的次序声明
表达式
避免在表达式中用赋值语句。
避免对浮点类型做等于或不等于判断。
不能将枚举类型进行运算后再赋给枚举变量。
在循环过程中不要修改循环计数器。
检测空指针,用 if( p )
检测非空指针,用 if( ! p )
函数
内联函数应将函数体放到类体外。虚函数不要设计为内联函数。
只有简单的函数才有必要设计为内联函数,复杂业务逻辑的函数不要这么做。
类
构造函数的初始化列表,应和类的顺序一致。
初始化列表中的每个项,应独占一行。
避免出现用一个成员初始化另一个成员。
构造函数应初始化所有成员,尤其是指针。
不要在构造函数和析构函数中抛出异常。
如果类可以继承,则应将类析构函数设计为虚函数。
如果类不允许继承,则应将类析构函数设计为非虚函数。
如果类不能被复制,则应将拷贝构造函数和赋值运算符设计为私有的。
如果为类设计了构造函数,则应有析构函数。
成员变量尽量避免使用mutable和Volatile。
尽量使用常成员函数代替非常成员函数,const函数
尽量避免使用友元函数和友元类。
大写"C"开头,后面字母反映具体含义,以清晰表达类的用途和功能为原则。接口必须以大写"I"开头,代表 Interface 。
错误处理
new和delete,new[]和delete[]成对使用。
申请内存完成之后,要检测指针是否申请成功,处理申请失败的情况。
谁申请谁释放。优先级:函数层面,类层面,模块层面。
释放内存完成后将指针赋空,避免出现野指针。
使用指针前进行判断合法性,应考虑到为空的情况的处理。
使用数组时,应先判断索引的有效性,处理无效的索引的情况。
代码不能出现编译警告。
使用错误传递的错误处理思想。
卫句风格:先处理所有可能发生错误的情况,再处理正常情况。
嵌套do-while(0)宏:目的是将一组语句变成一个语句,避免被其他if等中断。
性能
使用前向声明(Class M)代替#include指令。
尽量用++i代替i++。即用前缀代替后缀运算。
尽量在for循环之前,先写计算估值表达式。
尽量避免在循环体内部定义对象。
避免对象拷贝,尤其是代价很高的对象拷贝。
避免生成临时对象,尤其是大的临时对象。