他说“可以把程序的版式比喻为“书法”。好的“书法”可让人对程序一目了然,看得兴致勃勃。差的程序“书法”如螃蟹爬行,让人看得索然无味,更令维护者烦恼有加。”的确很有道理。。。
文件结构:
【规则1-2-1】为了防止头文件被重复引用,应当用ifndef/define/endif结构 产生预处理块。
【规则1-2-2】用 #include <filename.h> 格式来引用标准库的头文件(编译 器将从标准库目录开始搜索)。
【规则1-2-3】用 #include “filename.h” 格式来引用非标准库的头文件( 编译器将从用户的工作目录开始搜索)。
程序的版式:
【规则2-1-1】在每个类声明之后、每个函数定义结束之后都要加空行。
【规则2-1-2】在一个函数体内,逻揖上密切相关的语句之间不加空行,其它地 方应加空行分隔。
【规则2-2-1】一行代码只做一件事情,如只定义一个变量,或只写一条语句。 这样的代码容易阅读,并且方便于写注释。
【规则2-2-2】if、for、while、do等语句自占一行,执行语句不得紧跟其后。 不论执行语句有多少都要加{}。这样可以防止书写失误。
【规则2-3-1】关键字之后要留空格。象const、virtual、inline、case 等关 键字之后至少要留一个空格,否则无法辨析关键字。象if、for、 while等关键字之后应留一个空格再跟左括号‘(’,以突出关键字。
【规则2-3-2】函数名之后不要留空格,紧跟左括号‘(’,以与关键字区别。
【规则2-3-3】‘(’向后紧跟,‘)’、‘,’、‘;’向前紧跟,紧跟处不 留空格。
【规则2-3-4】‘,’之后要留空格,如Function(x, y, z)。如果‘;’不是一 行的结束符号,其后要留空格,如for (initialization; condition; update)。
【规则2-3-5】赋值操作符、比较操作符、算术操作符、逻辑操作符、位域操作 符,如“=”、“+=” “>=”、“<=”、“+”、“*”、“%”、“&& ”、“||”、“<<”,“^”等二元操作符的前后应当加空格。
【规则2-3-6】一元操作符如“!”、“~”、“++”、“--”、“&”(地址运 算符)等前后不加空格。
【规则2-3-7】象“[]”、“.”、“->”这类操作符前后不加空格。
【规则2-4-1】程序的分界符‘{’和‘}’应独占一行并且位于同一列,同时与 引用它们的语句左对齐。
【规则2-4-2】{ }之内的代码块在‘{’右边数格处左对齐。
【规则2-5-1】代码行最大长度宜控制在70至80个字符以内。代码行不要过长, 否则眼睛看不过来,也不便于打印。
【规则2-5-2】长表达式要在低优先级操作符处拆分成新行,操作符放在新行之 首(以便突出操作符)。拆分出的新行要进行适当的缩进,使排版整 齐,语句可读。
【规则2-6-1】应当将修饰符 * 和 & 紧靠变量名
例如:
char *name;
int *x, y; // 此处y不会被误解为指针
【规则2-7-1】注释是对代码的“提示”,而不是文档。程序中的注释不可喧宾 夺主,注释太多了会让人眼花缭乱。注释的花样要少。
【规则2-7-2】如果代码本来就是清楚的,则不必加注释。否则多此一举,令人 厌烦。例如 i++; // i 加 1,多余的注释
【规则2-7-3】边写代码边注释,修改代码同时修改相应的注释,以保证注释与 代码的一致性。不再有用的注释要删除。
【规则2-7-4】注释应当准确、易懂,防止注释有二义性。错误的注释不但无益 反而有害。
【规则2-7-5】尽量避免在注释中使用缩写,特别是不常用缩写。
【规则2-7-6】注释的位置应与被描述的代码相邻,可以放在代码的上方或右方 ,不可放在下方。
【规则2-7-8】当代码比较长,特别是有多重嵌套时,应当在一些段落的结束处 加注释,便于阅读。
命名规则:
【规则3-1-1】标识符应当直观且可以拼读,可望文知意,不必进行“解码”。
标识符最好采用英文单词或其组合,便于记忆和阅读。切忌使用汉语 拼音来命名。程序中的英文单词一般不会太复杂,用词应当准确。例 如不要把CurrentValue写成NowValue。
【规则3-1-2】标识符的长度应当符合“min-length && max-information”原 则。几十年前老ANSI C规定名字不准超过6个字符,现今的C++/C不再 有此限制。一般来说,长名字能更好地表达含义,所以函数名、变量 名、类名长达十几个字符不足为怪。那么名字是否越长约好?不见得! 例如变量名maxval就比maxValueUntilOverflow好用。单字符的名 字也是有用的,常见的如i,j,k,m,n,x,y,z等,它们通常可用作函数内 的局部变量。
【规则3-1-3】命名规则尽量与所采用的操作系统或开发工具的风格保持一致。
例如Windows应用程序的标识符通常采用“大小写”混排的方式,如 AddChild。而Unix应用程序的标识符通常采用“小写加下划线”的方 式,如add_child。别把这两类风格混在一起用。
【规则3-1-4】程序中不要出现仅靠大小写区分的相似的标识符。
【规则3-1-5】程序中不要出现标识符完全相同的局部变量和全局变量,尽管两 者的作用域不同而不会发生语法错误,但会使人误解。
【规则3-1-7】全局函数的名字应当使用“动词”或者“动词+名词”(动宾词 组)。类的成员函数应当只使用“动词”,被省略掉的名词就是对象 本身。例如:
DrawBox(); // 全局函数
box->Draw(); // 类的成员函数
【规则3-1-8】用正确的反义词组命名具有互斥意义的变量或相反动作的函数等
例如:
int minValue;
int maxValue;
【规则3-2-1】类名和函数名用大写字母开头的单词组合而成。
【规则3-2-2】变量和参数用小写字母开头的单词组合而成。
【规则3-2-3】常量全用大写的字母,用下划线分割单词。
const int MAX = 100;
【规则3-2-4】静态变量加前缀s_(表示static)。
static int s_initValue; // 静态变量
【规则3-2-5】如果不得已需要全局变量,则使全局变量加前缀g_(表示global )。例如:int g_howManyPeople; // 全局变量
【规则3-2-6】类的数据成员加前缀m_(表示member),这样可以避免数据成员 与成员函数的参数同名。
例如:
void Object::SetValue(int width, int height)
{
m_width = width;
m_height = height;
}
【规则3-2-7】为了防止某一软件库中的一些标识符和其它软件库中的冲突,可 以为各种标识符加上能反映软件性质的前缀。例如三维图形标准 OpenGL的所有库函数均以gl开头,所有常量(或宏定义)均以GL开头.
表达式和基本语句:
运算符的结合律,大部分都是从左到右结合,从右到左结合的有:
! ~ ++ -- (类型) sizeof
+ - * &
||
?:
【规则4-1-1】如果代码行中的运算符比较多,用括号确定表达式的操作顺序, 避免使用默认的优先级。
如 a = b = c = 0这样的表达式称为复合表达式。允许复合表达式存 在的理由是:(1)书写简洁;(2)可以提高编译效率。但要防止滥 用复合表达式。
【规则4-2-1】不要编写太复杂的复合表达式。
i = a >= b && c < d && c + f <= g + h ; // 复合表达式过于复杂
【规则4-2-2】不要有多用途的复合表达式。
d = (a = b + c) + r ;
该表达式既求a值又求d值。应该拆分为两个独立的语句:
a = b + c;
d = a + r;
【规则4-2-3】不要把程序中的复合表达式与“真正的数学表达式”混淆。
例如:
if (a < b < c) // a < b < c是数学表达式而不是程序表达式
并不表示
if ((a<b) && (b<c))
而是成了令人费解的
if ((a<b)<c )
【规则4-3-1】不可将布尔变量直接与TRUE、FALSE或者1、0进行比较。
根据布尔类型的语义,零值为“假”(记为FALSE),任何非零值都是 “真”(记为TRUE)。TRUE的值究竟是什么并没有统一的标准。例如 Visual C++ 将TRUE定义为1,而Visual Basic则将TRUE定义为-1。
假设布尔变量名字为flag,它与零值比较的标准if语句如下:
if (flag) // 表示flag为真
if (!flag) // 表示flag为假
其它的用法都属于不良风格,例如:
if (flag == TRUE)
if (flag == 1 )
if (flag == FALSE)
if (flag == 0)
【规则4-3-2】应当将整型变量用“==”或“!=”直接与0比较。
if (value == 0)
if (value != 0)
不可模仿布尔变量的风格而写成
if (value) // 会让人误解 value是布尔变量
if (!value)
【规则4-3-3】不可将浮点变量用“==”或“!=”与任何数字比较。
千万要留意,无论是float还是double类型的变量,都有精度限制。所 以一定要避免将浮点变量用“==”或“!=”与数字比较,应该设法转 化成“>=”或“<=”形式。
【规则4-3-4】应当将指针变量用“==”或“!=”与NULL比较。
if (p == NULL) // p与NULL显式比较,强调p是指针变量
if (p != NULL)
不要写成
if (p == 0) // 容易让人误解p是整型变量
if (p != 0)
或者
if (p) // 容易让人误解p是布尔变量
if (!p)
【规则4-5-1】不可在for 循环体内修改循环变量,防止for 循环失去控制。
【规则4-6-2】Switch语句中不要忘记最后那个default分支。即使程序真的不 需要default处理,也应该保留语句default : break; 这样做并非多 此一举,而是为了防止别人误以为你忘了default处理。
【建议1-2-1】头文件中只存放“声明”而不存放“定义”
在C++ 语法中,类的成员函数可以在声明的同时被定义,并且自动成 为内联函数。这虽然会带来书写上的方便,但却造成了风格不一致, 弊大于利。建议将成员函数的定义与声明分开,不论该函数体有多么 小。
【建议1-2-2】不提倡使用全局变量,尽量不要在头文件中出现象extern int value 这类声明。
【建议2-2-1】尽可能在定义变量的同时初始化该变量(就近原则)
【建议2-3-1】对于表达式比较长的for语句和if语句,为了紧凑起见可以适当 地去掉一些空格,如for (i=0; i<10; i++)和if ((a<=b) && (c<=d))
【建议3-1-1】尽量避免名字中出现数字编号,如Value1,Value2等,除非逻辑 上的确需要编号。这是为了防止程序员偷懒,不肯为命名动脑筋而导 致产生无意义的名字(因为用数字编号最省事)。
【建议4-4-1】在多重循环中,如果有可能,应当将最长的循环放在最内层,最 短的循环放在最外层,以减少CPU跨切循环层的次数。
【建议4-4-2】如果循环体内存在逻辑判断,并且循环次数很大,宜将逻辑判断 移到循环体的外面。