1.程序版式1.1.对齐1.1.1.程序块要采用缩进风格编写,缩进的空格数为4个。
使用VC提供的Tab键对齐。
1.1.2.“{”和“}”应独占一行并且位于同一列,同时引用他们的语句对齐1.1.3.{}之内的代码块在“{”右边数格外左对齐例:正确错误1.2.空行1.2.1.每个声明之后,每个函数定义之后要加空行1.2.2.在一个函数体内,逻辑上密切相关的语句之间不加空行,其它地方应加空行分隔1.2.3.变量声明和代码之间加空行1.2.4.函数返回语句用空行例:1.3.代码行1.3.1.一行代码只做一件事情,如只定义一个变量,或只写一条语句。
1.3.2.if、for、do、while、case、switch、default等语句自占一行,且if、for、do、while等语句的执行语句部分无论多少都要加括号{}例:示例:风格良好的代码行示例:风格不良的代码行1.4.空格1.4.1.关键字之后要留空格:const, virtual, inline, if, while, for1.4.2.函数名之后不要留空格1.4.3.“(”向后紧跟“,”,“、”,“.”,“;”,“)”向前紧跟1.4.4.“,”后要留空格,“”;之后如果不是一行的结束,后面要留空格1.4.5.赋值操作符,比较,算术,逻辑,第二元操作符前后加空格1.4.6.一元操作符!、~、++、--、—等前后不加空格1.4.7.像[]、“.”、—>等前后不加空格例:1.5.长行拆分1.5.1.代码行最长度宜控制在70到80个字符以内,代码行不宜过长1.5.2.长表达式拆分,应将操作符放在新行之首,拆分出新行要适当缩进,使排版整齐例:1.6.修饰的位置1.6.1.修饰符*和&应靠近变量名:char *name; int *x, y1.7.类的版式1.7.1.将public写前面,protect在其后,private写后面,以行为中心1.7.2.变量在函数声明之后1.7.3.逻辑相关的函数排列在一起例:class A{public:void Func1(void);void Func2(void);//空行int i, j;…protect:void Func3(void);void Func4(void);float x, y;…private:void Func5(void);void Func6(void);//空行string a, b;…}2.代码注释规则(范例文件)2.1.每个文件头2.1.1.阐述该文件包含的内容2.1.2.对include的文件要注释2.2.每个函数的头部2.2.1.注明函数名称、函数说明、输入参数和返回值2.3.每个类(即头文件)2.3.1.注明类的用途2.4.函数当中需要注释不易明折的地方2.4.1.算法2.4.2.设计思想2.4.3.独到的用处2.5.原则2.5.1.注释和代码一样要及时更新2.5.2.注释不是代码的重复2.5.3.全部使用“//”方式注释2.5.4.注释尽量不要单独占一行2.5.5.注释要简洁、明了2.5.6.边写代码边写注释,MFC自带的代码注释不用修改2.5.7.对于所有有物理含义的变量、常量,如果其命名不是充分自注释的,在声明时都必须加以注释,说明其物理含义。
变量、常量、宏的注释应放在其上方相邻位置或右方。
2.5.8.将注释与其上面的代码用空行隔开3.命名规范3.1.共性规则3.1.1.不可用汉语拼音,用英文、用词应准确3.1.2.应用大小写混排方式,如:AddChild3.1.3.程序中不要出现仅靠大小写区分的相似的标识符3.1.4.程序中不要出现标识符完全相同的简单变量和全局变量3.1.5.变量名应当使用“名词”或“形容词+名词”,如:float fValue;float fOldVlaue;float fNewValue;3.1.6.函数名应使用动词或动词+名词,如:void GetValue();3.1.7.用正确的反义词组命名具有互斥定义的变量或相反动作的函数,如:int nMinValue;int nMaxValue;int nSetValue;int nGetValue;3.1.8.对于借来的代码,不改变其命名3.2.命名规则3.2.1.类名和函数名用大写字母开头的单词组合而成,如:class Node;class LeafNode;void SetValue();3.2.2.变量和参数用小写字母开头的单词组合而成,如:BOOF bflag,;int nDrawMode;float fHeight;string strTitle;char cSource;3.2.3.常量全用大写字母,用下划线分割单词DDD_SAF3.2.4.静态变量前加前缀s_,如:Static int s_initValue;3.2.5.如果不得已需要全局变量,全局变量前加前缀g_,如:int g_howManyPeople3.2.6.类的数据成员加前缀m_,如:void objet::Set Value(int width, int height){m_width=width;m_height=height}3.2.7.适当使用匈牙利命名法4.程序规范4.1.语句4.1.1.对运算符很多的情况下,应该使用括号区分运算的顺序例如:word = (high << 8) | lowif ((a | b) && (a & c))4.1.2.if 语句4.1.2.1.布尔变量与零值比较时,不可将布尔变量直接与TRUE、FALSE或者1、0进行比较假设布尔变量名字为flag,它与零值比较的标准if语句如下:if (flag) // 表示flag为真if (!flag) // 表示flag为假其它的用法都属于不良风格,例如:if (flag == TRUE)if (flag == 1 )if (flag == FALSE)if (flag == 0)4.1.2.2.整型变量与零值比较时,应当将整型变量用“==”或“!=”直接与0比较假设整型变量的名字为value,它与零值比较的标准if语句如下:if (value == 0)if (value != 0)不可模仿布尔变量的风格而写成if (value) // 会让人误解 value是布尔变量if (!value)4.1.2.3.浮点变量与零值比较时,不可将浮点变量用“==”或“!=”与任何数字比较千万要留意,无论是float还是double类型的变量,都有精度限制。
所以一定要避免将浮点变量用“==”或“!=”与数字比较,应该设法转化成“>=”或“<=”形式。
假设浮点变量的名字为x,应当将if (x == 0.0) // 隐含错误的比较转化为if ((x>=-EPSINON) && (x<=EPSINON))其中EPSINON是允许的误差(即精度)。
4.1.2.4.指针变量与零值比较时,应当将指针变量用“==”或“!=”与NULL比较指针变量的零值是“空”(记为NULL)。
尽管NULL的值与0相同,但是两者意义不同。
假设指针变量的名字为p,它与零值比较的标准if语句如下:if (p == NULL) // p与NULL显式比较,强调p是指针变量if (p != NULL)不要写成if (p == 0) // 容易让人误解p是整型变量if (p != 0)或者if (p) // 容易让人误解p是布尔变量if (!p)4.1.2.5.程序中有时会遇到if/else/return的组合,应该将如下不良风格的程序例如:if (condition)return x;return y;改写为if (condition){return x;}else{return y;}或者改写成更加简练的return (condition ? x : y);4.1.3. 循环语句4.1.3.1. 在多生循环中,如果有可能,应将最长的循环放在最内层,最短的循环放在最外层,以减少CPU 跨越循环层的次数例:4.1.3.2.如果循环体内存在逻辑判断,并且循环次数很大,宜将逻辑判断移到循环体的外面 4.1.3.3. switch 语句的case 分支如果不要break ,要注释,同时要加default 语句 例:switch 语句的基本格式是:switch (variable) {case value1 : …break;case value2 : …break;…default : …break;}4.2.常量4.2.1.只使用const常量,不使用宏常量(自定义)4.2.2.需要对外公开的常量放在头文件(*.h)中,不需要对外公开的常量放在定义文件(*.cpp)的头部4.2.3.不能在类中初始化const常量,只能通过枚举常量来解决例:错误:class A{const int SIZE=100; (错误)int array[SIZE];}正确:class A{…enum { SIZE1 = 100, SIZE2 = 200}; // 枚举常量int array1[SIZE1];int array2[SIZE2];};4.3.函数4.3.1.参数规则4.3.1.1.参数书写要完整,不能只写类型,不写参数名,如果函数没有参数,用void填充例如:void SetValue(int width, int height); // 良好的风格void SetValue(int, int); // 不良的风格float GetValue(void); // 良好的风格float GetValue(); // 不良的风格4.3.1.2.如果参数是指针,且仅作输入用,则应在类型前加const,以免指针在函数体内被意外修改;一般地,应将目的参数放在前面,源参数放在后面例:void StrngCopy(char *strlDestintion, const har *StrSource)4.3.1.3.如果参数以值传递的方式传递对象,则宜改用“const &”方法传递,能提高效率4.3.1.4.避免函数有太多的参数,参数个数应尽量控制在5个以内4.3.1.5.尽量不要使用类型和数目不确定的参数例:int printf(const cha*format[, argument]…);4.3.1.6.对于内置类型参数要传值4.3.1.7.需要传指针不传引用的情形a)内部需要用NULL状态(引用没有NULL状态)b)若参数是被new出来的,是将在函数内被释放4.3.2.返回值规则4.3.2.1.函数的输出值结果用输出参数(一般为指针)获得,状态用return返回4.3.2.2.如果返回一个对象,一般用引用传递,但有的情况下必须用值传递例如:class String{…// 赋值函数String & operate=(const String &other);// 相加函数,如果没有friend修饰则只许有一个右侧参数friend String operate+( const String &s1, const String &s2);private:char *m_data;}String的赋值函数operate = 的实现如下:String & String::operate=(const String &other){if (this == &other){return *this;}delete m_data;m_data = new char[strlen(other.data)+1];strcpy(m_data, other.data);return *this; // 返回的是 *this的引用,无需拷贝过程}对于赋值函数,应当用“引用传递”的方式返回String对象。