本编码规范
针对
C++
语言。
制定本规范的目的:
提高代码的健壮性,使代码更安全、可靠;
提高代码的可读性,使代码易于查看和维护。
本文档分别对
C++
程序的格式、注释、标识符命名、语句使用、函数、类、程序组织、公共变量等方面做出了要求。规范分为两个级别——规则和建议。规则级的规范要求开发人员必须要遵守,建议级的规范开发人员应尽量遵守。
各项目组在用
C++
语言或基于
C++
语言的开发工具开发项目时,要遵守本规范。
以下是各条规范的具体内容。
对代码书写格式的要求。
规范级别:
规则
规则描述:
●
在头文件和实现文件中,各主要部分之间要用空行隔开。
所谓文件的主要部分,包括:序言性注释、防止被重复包含部分(只在头文件中)、
# include
部分、
#define
部分、类型声明和定义部分、实现部分等等。
●
在一个函数中,完成不同功能的部分,要用空行隔开。
理由:
段落分明,提高代码的可读性。
规范级别:
规则
规则描述:
●
在使用赋值运算符、逻辑运算符、位运算符、算术运算符等二元操作符时,在其两边各加一个空格。
例:
nCount = 2
;而不是
nCount=2
;
●
函数的各参数间要用“,”和一个空格隔开。
例:
void GetDate(int x, int y)
;
而不是
void GetDate(int x,int y)
或
void GetDate(int x ,int y)
。
理由:
提高代码的可读性。
规范级别:
规则
规则描述:
●
不要在引用操作符前后使用空格,引用操作符指“.”和“
->
”,以及“
[]
”。
●
不要在“::”前后使用空格。
●
不要在一元操作符和其操作对象之间使用空格,一元操作符包括“
++
”、“
--
”“!”、“
&
”“
*
”等。
理由:
提高代码的可读性。
举例:
// 不要象下面这样写代码:
m_pFont -> CreateFont();
//应该写成这样
m_pFont->CreateFont();
规范级别:
规则
规则描述:
对程序语句要按其逻辑进行水平缩进,以两个空格或一个
Tab
符为单位(建议使用空格),使同一逻辑层次上的代码在列上对齐。
理由:
提高代码的可读性。
规范级别:
规则
规则描述:
较长的语句要分成多行书写。长表达式要在低优先级操作符处分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,缩进长度以两个空格或
Tab
符长度为单位。
理由:
提高代码的可读性。
举例:
// 下面是一个处理的较为合理的例子
nCount = Fun1(n1, n2, n3)
+ (nNumber1 * GetDate(n4, n5, n6)) * nNumber1;
规范级别:
规则
规则描述:
控制语句(if , for , while , do...whule)的语句部分一定要用 ‘{ ’和‘ }’括起来(即使只有一条语句),并且‘{ ’和‘ }’
应处在同一列上。
理由:
这样做,能够
划分出清晰的语句块,
使语句的归属明确,使代码更加容易阅读和修改。
举例:
//不要象下面这样写代码:
if (x == 0)
return;
else
while (x > min)
x--;
// 应该这样写
if (x == 0)
{
return;
}
else
{
while (x > min)
{
x--;
}
}
规范级别:
规则
规则描述:
一行只写一条程序语句。
理由:
提高代码的可读性。
举例:
// 不要这样写
x = x0; y = y0;
while(IsOk(x)) {x++;}
// 应该这样写代码
x = x0;
y = y0;
while(IsOk(x))
{
x++;
}
2.1.8
一次只声明、定义一个变量
规范级别:
规则
规则描述:
一次(一条声明、定义语句)只声明、定义一个变量。
理由:
提高代码的可读性。
举例:
// 应该这样写
int width;
int length;
// 不要这样写
int width, length;
规范级别:
建议
规则描述:
对于一个表达式,在一个二元、三元操作符操作的操作数的两边,应该放置“(”和“)”。
理由:
避免出现不明确的运算、赋值顺序,提高代码的可读性。
举例:
// 下面这行代码:
result = fact / 100 * number + rem;
//最好写成这样
result =
((fact / 100) * number) + rem
;
2.1.10将
操作符“
*
”、“
&
”和类型写在一起
规范级别:
规则
规则描述:
在定义指针、引用变量时,将操作符“*”、“&”和类型写在一起。
理由:
统一格式,提高代码的可读性。
举例:
// 不要象下面这样写代码:
char *s;
//而应该写成这样
char* s;
这一部分对程序注释提出了要求。
程序中的注释是程序与日后的程序读者之间通信的重要手段。良好的注释能够帮助读者理解程序,为后续阶段进行测试和维护提供明确的指导。
下面是关于注释的基本原则:
1.
注释内容要清晰明了,含义准确,防止出现二义性。
2.
边写代码边注释,修改代码的同时修改相应的注释,保证代码与注释的一致性。
规范级别:
规则
规则描述:
●
在函数的声明之前,要给出精练的注释(不必牵扯太多的内部细节),让使用者能够快速获得足够的信息使用函数。格式不做具体要求。
●
在函数的定义之前,要给出足够的注释。注释格式要求如下:
/*************************************************************************
【函数名称】 (必需)
【函数功能】 (必需)
【参数】 (必需。标明各参数是输入参数还是输出参数。)
【访问变量】 (必需。列出该函数访问的全局变量、成员变量。)
【返回值】 (必需。解释返回值的意义。)
【使用情况】 (必需。调用其它函数的情况,被调用的情况)
【开发者及日期】 (必需)
【版本】 (必需)
【更改记录】 (若有修改,则必需注明)
*************************************************************************/
理由:
提高代码的可读性。
规范级别:
规则
规则描述:
●
在类的声明之前,要给出足够而精练的注释。注释格式要求如下:
/*************************************************************************
【类名】 (必需)
【功能】 (必需)
【接口说明】 (必需)
【开发者及日期】 (必需)
【版本】 (必需)
【版权信息】 (可选)
【更改记录】 (若修改过则必需注明)
*************************************************************************/
理由:
提高代码的可读性。
规范级别:
规则
规则描述:
在头文件、实现文件的首部,一定要有文件注释,用来
介绍文件内容。注释格式要求如下:
/*************************************************************************
【文件名】 (必需)
【功能模块和目的】 (必需)
【开发者及日期】 (必需)
【版本】 (必需)
【版权信息】 (必需)
【更改记录】 (若修改过则必需注明)
*************************************************************************/
理由:
提高代码的可读性。
规范级别:
建议
规则描述:
建议
对每个空循环体给出确认性注释。
理由:
提示自己和别人,这是空循环体,并不是忘了。
举例:
while(g_bOpen == FALSE)
{
//空循环
}
规范级别:
建议
规则描述:
建议
对多个
case
语句共用一个出口的情况给出确认性注释。
理由:
提示自己和别人,这几
个
case
语句
确实是共用一个出口,并不是遗漏了。
举例:
switch(nNumber)
{
case 1:
nCount++;
break;
case 2:
case 3:
nCount--;
break; //
当
nNumber
等于
2
或
3
时,
进行同样的处理
default:
break;
}
规范级别:
建议
规则描述:
除上面说到的,对于以下情况,也应该考虑进行注释:
l
变量的声明、定义。通过注释,解释变量的意义、
存取关系等;
例如:
int m_nNumber; //
记录图形个数。被
SetDate( )
、
GetDate( )
使用。
l
数据结构的声明。通过注释,解释数据结构的意义、
用途等;
例如:
//定义结构体,存储元件的端点。用于将新旧的端点对应。
typedef struct
{
int nBNN;
int nENN;
int nBNO;
int nENO;
}Element;
l
分支。通过注释,解释不同分支的意义;
例如:
if(m_iShortRadio == 0) //三相的情况
{
strvC.Format("%-10.6f", vC);
straC.Format("%-10.6f", aC);
}
else if(m_iShortRadio == 1) //两相的情况
{
strvC = _T("");
straC = _T("");
}
l
调用函数。通过注释,解释调用该函数所要完成的功能;
例如:
SetDate(m_nNumber ); //
设置当前的图形个数。
l
赋值。
通过注释,
说明赋值的意义;
例如:
m_bDraw = true; //
将当前设置为绘图状态
l
程序块的结束处。
通过注释,
标识程序块的结束。
例如:
if (name = = White)
{
…
if (age = = 20)
{
…
}//
年龄判断、处理结束
…
}//
姓名判断、处理结束
l
其它有必要加以注释的地方
;
理由:
提高代码的可读性。
规范级别:
建议
规则描述:
同一个函数或模块中的行末注释应尽量对齐。
理由:
提高代码的可读性。
举例:
nCount = 0; //
计数器,表示正在处理第几个数据块
BOOL bNeedSave; //
是否保存从服务器返回的数据
BOOL bReturnCache; //
是否将
Cache
中的内容返回客户端
DWORD BytesWritten; //
写入的数据长度
规范级别:
规则
规则描述:
注释行的数量不得少于程序行数量的
1/3
。
对标识符和文件的命名要求。
规范级别:
规则
规则描述:
在程序中声明、定义的
变量、常量、宏、类型、函数
,在对其命名时应该遵守统一的命名规范。具体要求如下:
<! l一般变量
一般变量名应以小写字母打头,各英文描述单词的首字母分别大写,其他字母一律小写。对于不同作用域的变量,其命名要求如下表所示:
表2-1 变量命名
变量种类
|
前缀要求
|
示例
|
全局变量
|
g_
|
g_Number
|
全局指针变量
|
g_p
|
g_pNumber
|
对象级变量(类内数据成员)
文件作用域变量(文件中静态变量)
|
m_
|
m_Number
|
对象级指针变量(类内指针数据成员)
文件作用域指针变量(文件中静态指针变量)
|
m_p
|
m_pNumber
|
函数级变量(局部变量)
|
无要求
|
number
|
函数级指针变量(局部指针变量)
|
p
|
pNumber
|
上表列出了对变量命名的基本要求。项目组或程序员可在该要求上再进行细化,但必须保证符合该要求。
<! l常量
常量的名字要全部大写。常量指:
const修饰的量。如const int NUMBER = 100;
枚举量。如enum{ ONE,TWO,THREE };
<! l宏
所有用宏形式定义的名字,包括宏常量和宏函数,名字要全部大写。
<! l类型
自定义类型名应以大写字母打头。C++中自定义类型包括:class、struct、enum、union、typedef声明的类型、namespace。
例如:typedef struct Student;
class CMsgDialog;
<! l函数
函数名应以大写字母打头。
例如:void GetCount();
下面还有一些在命名时应该遵守的基本规范:
<! l名中含多于一个单词时,每个单词的第一个字母大写。
例如:m_LastCount 中要大写L和C;
<! l不要使用以下划线“_”打头的标识符。
例如:_bFind 是不允许出现的变量;
<! l不要使用仅用大小写字母区分的名称。
例如:m_bFind 和 M_BFIND;
<! l尽量使用有意义的名字。应做到见其名知其意。
例如:m_strError 表示错误的字符串;
理由:
减少命名冲突;提高代码的可读性。
规范级别:
规则
规则描述:
在程序中声明、定义的
变量、常量、宏、类型、函数
,它们的名字长度要在
4
至
25
个字符之内(下限不包括前缀,上限包括名字中所有的字符)。
对于某些已经被普遍认同的简单命名,可不受本规则的限制。如
for
循环的循环记数变量,可使用
i
、
j
等简单字符命名。
理由:
名字长度应该在一个恰当的范围内,名字太长不够简洁,名字太短又不能清晰表达含义。
规范级别:建议
规则描述:
代码文件的名字要与文件中声明、定义的类的名字基本保持
一致,使类名与类文件名建立联系。
理由:
使应用程序容易理解。
举例:
将类CMsgDialog的头文件和实现文件命名为msgdialog.h和msgdialog.cpp就是一种比较简单、恰当的方法。
对具体程序语句的使用要求。
规范级别:建议
规则描述:
在一条程序语句中,只应包含一个赋值操作符。赋值操作符包括:=, +=, -=, *=, /=, %=, >>=, <<=, &=, |=,^=, ++, --。
理由:
避免产生不明确的赋值顺序。
举例:
// 不要这样写
b = c = 5;
a = (b * c) + d++;
// 应该这样写
c = 5;
b = c;
a = (b * c) + d;
d++;
规范级别:
建议
规则描述:
不要在控制语句
if
,
while
,
for
和
switch的条件表达式中使用
赋值操作符。赋值操作符包括:
=
,
+=
,
-=
,
*=
,
/=
,
%=
,
>>=
,
<<=
,
&=
,
|=
,
^=
,
++
,
--。
理由:
一个类似于
if (x = y)这样的写法是
不明确、不清晰的,代码的作者也许是想写成这样:
if (x == y)。
举例:
//不要象下面这样写代码:
if (x -= dx)
{
...
}
//应该这样写:
x -= dx;
if (x)
{
...
}
规范级别:
建议
规则描述:
在一个赋值表达式中:
• 一个左值,在表达式中应该仅被赋值一次。
• 对于多重赋值表达式,一个左值在表达式中仅应出现一次,不要重复出现。
理由:
避免产生不明确的赋值顺序。
举例:
//不要象下面这样写代码:
i = t[i++];//
一个左值,在表达式中应该仅被赋值一次
a = b = c + a; //
对于多重赋值表达式,一个左值在表达式中仅应出现一次,不能重复出
现。
i = t[i] = 15; //
对于多重赋值表达式,一个左值在表达式中仅应出现一次,不能重复出现。
规范级别:
建议
规则描述:
对于
if
,
while
,
for等
控制语句
的条件表达式,建议使用正规的布尔格式。
理由:
使代码更容易理解。
举例:
//不要象下面这样写代码:
while(1)
{
...
}
if(test)
{
...
}
for(i = 1; function_call(i); i++)
{
...
}
//最好这样写:
AlwaysTrue = true;
while(AlwaysTrue == true)
{
...
}
if(test == true)
{
...
}
for(i = 1; function_call(i) == true; i++)
{
...
}
规范级别:
规则
规则描述:
程序中不要使用goto语句。
理由:
这条规则的目的是为了确保程序的结构化,因为滥用goto语句会使程序流程无规则,可读性差。
Goto语句只在一种情况下有使用价值,就是当要从多重循环深处跳转到循环之外时,效率很高,但对于一般要求的软件,没有必要费劲心思追求多么高的效率,而且效率主要是取决于算法,而不在于个别的语句技巧。
规范级别:
规则
规则描述:
在控制语句 (
for
,
do
,
while
) 块中,禁止使用
Break和continue。
在
switch中的case语句块不受该规则限制。
理由:
在控制语句 (
for
,
do
,
while
) 块中
使用Break和continue,会
打乱代码结构化的流程,使代码
的可读性降低。
规范级别:
规则
规则描述:
字符串的赋值应采用
_T(“”)
模式。
理由:
改善可移植性。
举例:
//不要象下面这样写代码:
Cstring strError = “syntax error”
;
//应该这样写:
Cstring strError = _T(“syntax error”)
;
规范级别:
规则
规则描述:
不要对浮点类型的数据做等于、不等于这些精确的比较判断,要用范围比较代替精确比较。
理由:
由于存在舍入的问题,计算机内部不能精确的表示所有的十进制浮点数,用等于、不等于这种精确的比较方法就可能得出与预期相反的结果。所以应该用大于、小于等
范围比较的方法代替精确比较的方法。
举例:
//不要象下面这样写代码:
float number;
… …
if (number = = 0) //
精确比较
… …
规范级别:
规则
规则描述:
局部的
new
和
delete
要成对出现;
new
要与
delete
对应,
new[]
要与
delete[]
对应。
理由:
防止内存泄露。
规范级别:规则
规则描述:
switch语句中的每一个case分支,都要以
break作为
分支的
结尾(几个连续的空
case语句允许共用一个)。
理由:
使代码更容易理解;减少代码发生错误的可能性。
规范级别:规则
规则描述:
在switch语句块中,一定要有
default分支来处理其它情况。
理由:
用来处理switch语句中默认、特殊的情况。
规范级别:
建议
规则描述:
在定义指针变量的同时,对其进行初始化。如果定义时还不能为指针变量赋予有效值,则使其指向NULL。
理由:
减少使用未初始化指针变量的几率。
举例:
// 不要这样写代码
int* y ;
y = &x ;
...
// 应该这样写
int* y = &x;
...
规范级别:
建议
规则描述:
当指针变量所指的内存被释放后,应该赋予指针一个合理的值。除非该指针变量本身将要消失这种情况下不必赋值,否则应赋予NULL。
理由:
保证指针变量在其生命周期的全过程都指向一个合理的值。
规范级别:规则
规则描述:
在代码中用ptr->fld的形式代替(*ptr).fld的形式。
对函数的要求。
规范级别:
规则
规则描述:
函数体代码长度不得超过
100
行(不包括注释)。
理由:
明确函数功能(一个函数仅完成一件事情),精确(而不是近似)地实现函数设计。
规范级别:
建议
规则描述:
将重复使用的简单操作编写成函数。
理由:
对于重复使用的功能,虽然很简单,也应以函数的形式来处理,这样可以简化代码,使代码更易于维护。
2.5.3
尽量保持函数只有唯一出口
规范级别:
规则
规则描述:
应该尽量保证一个函数只有一个
出口。
理由:
增加函数的可靠性。
规范级别:
规则
规则描述:
在声明和定义函数时,
在函数参数列表中为各参数指定类型和名称。
理由:
提高代码的可读性,改善可移植性。
举例
:
//
不要象下面这样写代码:
f(int, char*); //
函数
声明
f(a, b) //
函数
定义
int a;
char* b
{
...
}
//
应该这样写:
f(int a, char* b);
f(int a, char* b)
{
...
}
规范级别:
规则
规则描述:
要
为每一个函数指定它的返回值。如果函数没有返回值,则要定义返回类型为
void。
理由:
提高代码的可读性;改善代码的可移植性。
规范级别:
建议
规则描述:
函数调用语句中,在函数的参数列表中不要使用赋值操作符。赋值操作符包括
=
,
+=
,
-=
,
*=
,
/=
,
%=
,
>>=
,
<<=
,
&=
,
|=
,
^=
,
++
,
--。
理由:
避免产生不明确的赋值顺序。
举例
:
//
不要象下面这样写代码:
void fun1(int a);
void fun2(int b)
{
fun1(++b); //
注意这里
!
}
规范级别:
规则
规则描述:
编写可重入函数时,若操作全局变量,则应加以保护。
举例
:
如果全局变量不加以保护,当多个线程调用此函数时,很可能使此变量变为不可知状态。
例如:假设
Exam
是
int
型全局变量,函数
Squre_Exam
返回
Exam
平方值,如下函数不具有可重入性。
Unsigned int example (int para)
{
unsigned int temp;
<!--
Exam = para;
temp = Square_Exam();
return temp;
}
此函数若被多个线程调用,
Exam
可能成为未知的。
可改为如下方式:
Unsigned int example (int para)
{
unsigned int temp;
[
申请信号量操作
]
Exam = para;
temp = Square_Exam();
[
释放信号量操作
]
return temp;
}
对类的要求。
规范级别:
规则
规则描述:
为每一个类显示定义默认构造函数。
理由:
确保类的编写者考虑在类对象初始化时,可能出现的各种情况。
举例:
class CMyClass
{
CMyClass();
...
};
规范级别:
规则
规则描述:
当类中包含指针类型的数据成员时,必须显示的定义拷贝构造函数。建议为每个类都显示定义拷贝构造函数。
理由:
确保类的编写者考虑类对象在被拷贝时可能出现的各种情况。
举例:
class
CMyClass
{
...
CMyClass
(
CMyClass
& object);
...
};
规范级别:规则
规则描述:
当类中包含指针类型的数据成员时,必须显示重载“=”操作符。建议为每个类都显示重载“=”操作符。
理由:
确保类的编写者考虑将一个该类对象赋值给另一个该类的对象时,可能出现的各种情况。
举例:
//
应该这样写代码
class CMyClass
{
...
operator = (const CMyClass& object);
...
};
规范级别:
规则
规则描述:
为每一个类显示的定义析构函数。
理由:
确保类的编写者考虑类对象在析构时,可能出现的各种情况。
举例:
class
CMyClass
{
...
~
CMyClass
(
CMyClass
& object);
...
};
该规则参考自《
Effective C++
》中的条款
14
。
规范级别:
规则
规则描述:
基类的析构函数一定要为虚拟函数(
virtual
Destructor)。
理由:
保证
类对象内存被释放之前,
基类和派生类的
析构函数都被调用。
规范级别:
规则
规则描述:
在派生类中不要对基类中的非虚函数重新进行定义。
如果确实需要在派生类中对该函数进行不同的定义,那么应该在基类中将该函数声明为
虚函数;
理由:
不要忘了,当通过一个指向对象的指针调用成员函数时,最终调用哪个函数取决于指针本身的类型,而不是指针当前所指向的对象。
规范级别:建议
规则描述:
用内联函数代替宏函数。
理由:
同宏函数相比,内联函数不但具有宏函数的效率,而且使用起来更安全。
该规则参考自《
Effective C++
》中的条款
10
。
规范级别:
规则
规则描述:
如果你为一个类重载了操作符
new
,那你也应该为这个类重载
操作符
delete
。
理由:
操作符
new
和
操作符
delete
需要一起合作。
规范级别:
规则
规则描述:
类对外的接口应该是完全功能化的,类中可以定义Public的成员函数,但不应该有Public的数据成员。
理由:
要想改变对象的当前状态,应该通过它的成员函数来实现,而不应该通过直接设置它的数据成员这种方法。一个类的数据成员应该声明为
private的,最起码也应该是protected的。
规范级别:
建议
规则描述:
当继承的层数超过
5
层时,问题就很严重了,需要有特别的理由和解释。
理由:
●
很深的继承通常意味着未做通盘的考虑;
●
会显著降低效率;
●
可以尝试用类的组合代替过多的继承;
●
与此类似,同层类的个数也不能太多,否则应该考虑是否要增加一个父类,以便做某种程度上的新的抽象,从而减少同层类的个数。
规范级别:
建议
规则描述:
C++
提供多继承的机制。多继承在描述某些事物时可能是非常有利的,甚至是必须的,但我们在使用多继承的时,一定要慎重,在决定使用多继承时,确实要有非常充分的理由。
理由:
多继承会显著增加代码的复杂性,还会带来潜在的混淆。比如在很多
C++
书籍中提到的菱形继承问题,如下图所示:
图2-1
菱形继承
A
派生子类
B
、
C
,
D
多继承于
B
、
C
。这种情况下,会导致类
D
的对象中有两个类
A
子对象。
规范级别:
建议
规则描述:
类设计的同时,考虑类的可复用性。
对程序组织的要求。
规范级别:
规则
规则描述:
在
一个头文件中,只应该包含对一个类的声明(嵌套类的情况除外)。头文件是指以.h、.hh、.H、.hxx、.hpp为后缀的文件。
理由:
提高代码的可读性。
规范级别:
规则
规则描述:
在一个源文件中定义的每一个函数,都应该属于同一个类,即对一个类的实现描述要独占一个文件。源文件指以*.cc, *.cxx, *.cpp, *.C or *.c为后缀的代码文件。
理由:
提高代码的可读性。
规范级别:规则
规则描述:
在头文件中
只包含声明,
不要包含全局变量和函数的定义。头文件指以.h、 .hh、.H、 .hxx、.hpp为后缀的代码文件。
内联函数的情况除外。
理由:
在头文件中只应该包含各种声明,而不应该包含具体的实现。
规范级别:
规则
规则描述:
在源文件中只应该包含对类的实现,不应该包含任何类的声明。类声明应该统一放到头文件中去。源文件指以*.cc, *.cxx, *.cpp, *.C or *.c为后缀的代码文件。
理由:
提高代码的可读性。
规范级别:规则
规则描述:
只允许头文件被包含到其它的代码文件中去。
理由:
改善程序代码的组织结构。
2.7.6
避免头文件的重复包含
规范级别:
规则
规则描述:
头文件的格式应该类似于:
#ifndef <IDENT>
#define <IDENT>
...
...
#endif
或者
#if !defined (<IDENT>)
#define <IDENT>
...
...
#endif
上面的
<IDENT>是一个标识字符串,
要求该
标识字符串必须唯一。建议使用该文件的答谢文件名。
理由:
避免对同一头文件的重复包含。
举例:
// 对于文件audit.h,它的文件结构应该为:
#ifndef AUDIT_H
#define AUDIT_H
...
...
#endif
对公共变量(全局变量)的要求。
规范级别:
建议
规则描述:
在程序中要尽可能少的使用公共变量。在决定使用一个公共变量时,要仔细考虑,权衡得失。
理由:
公共变量会增大模块间的耦合。
规范级别:
规则
规则描述:
当你真的决定使用公共变量时,要仔细定义并明确公共变量的含义、作用、取值范围、与其它变量间的关系。明确公共变量与操作此公共变量的函数之间的关系,如访问、修改和创建等。
2.8.3
防止公共变量与局部变量重名
规范级别:
规则
规则描述:
防止公共变量与局部变量重名。
下面这几条要求,不适合合并到上面任何一类,所以单独作为一部分。
规范级别:建议
规则描述:
在C++中,不要再使用struct。
理由:
以符合面向对象的思想。
规范级别:建议
规则描述:
在C++中,不要再使用union。
理由:
●
由于union成员公用内存空间所以容易出错,并且维护困难;
●
使用union通常意味着非面向对象的方法。
规范级别:
规则
规则描述:
使用
const来定义常量,
代替通过宏来定义常量的方法。
理由:
在不损失效率的同时,使用
const
常量比宏更加安全。
举例:
//
宏定义的方法
#define string "Hello world!"
#define value 3
//常量定义的方法可以代替宏,且要更好
const char* string = "Hello world!";
const int value = 3;
规范级别:
规则
规则描述:
对于宏的展开部分,在宏的参数出现的地方要加括号“()”。
理由:
保证宏替换的安全,同时提高代码的可读性。
举例:
// 不要这样写
#define GET_NAME(obj,ind) obj->name[ind]
// 应该这样写
#define GET_NAME(obj,ind) (obj)->name[ind]
该规则参考自《
More Effective C++
》中的条款
2
。
规范级别:
建议
规则描述:
用
C++
提供的类型转换操作符(
static_cast
,
const_cast
,
dynamic_cast
和
reinterpret_cast
)代替
C
风格的类型转换符。
理由:
C
风格的类型转换符有两个缺点:
1
允许你在任何类型之间进行转换,即使在这些类型之间存在着巨大的不同。
2
在程序语句中难以识别。
规范级别:
规则
规则描述:
将程序中不再用到的、注释掉的代码及时清除掉。
理由:
理由不用做太多的解释了吧?没有用的东西就应该清理掉。如果觉得这些代码你可能以后会用到,可以备份到其它地方,而不要留在正式的版本里。
以上就是我们要求
C++
程序遵守的规范的全部内容。