编程规范CPP.docx
- 文档编号:9480536
- 上传时间:2023-05-19
- 格式:DOCX
- 页数:22
- 大小:24.33KB
编程规范CPP.docx
《编程规范CPP.docx》由会员分享,可在线阅读,更多相关《编程规范CPP.docx(22页珍藏版)》请在冰点文库上搜索。
编程规范CPP
编程规范——C,Pro*C,C++
创建日期:
2001-06-12
目录
目录1
介绍2
内容2
命名规则2
类型命名规则2
表示变量作用域的前缀2
表示变量数据类型的前缀3
文档和注释5
文档和注释5
文件头注释5
函数头注释6
有关修改的注释6
文件组织7
头文件定义7
代码风格8
概述8
括号8
续行8
空格9
特定的结构10
有关临时的修改11
范例型条件编译指令12
程序实现13
恰当的访问权限13
常量13
静态成员引用13
不要隐藏变量13
声明13
赋值14
括号14
返回值14
内存分配的处理15
其他15
语言特定规范17
Pro*C的一个例子:
17
介绍
内容
本文基于编程规范——总则(以下简称总则),制定了Windows平台下的C++及Unix平台下的C,Pro*C,C++的编程规范。
命名规则
命名规则遵照总则执行,另增加如下表述:
Unix平台中,标示符以小写结合下划线为主,Windows平台中,标示符以大写分隔的混合大小写为主。
类型命名规则
平台
标识符类型
命名规则
例
C,C++,Pro*C
struct
混合大小写,首字母大写。
typedefstruct_MyStruct{
}MyStruct;
C++
类(class)和接口(interface)
混合大小写,首字母大写。
classNewIdeaStep{};
interfaceIdeaSorter{};
C,C++,Pro*C
外部函数
首字母小写。
sprintf()
dumpAllLog()do_move()
C++
成员函数
首字母小写。
run()
getSpeed()get_speed()
C,Pro*C
常量
全大写,下划线分隔。
#defineMAX_SIZE64
C++
常量
全大写,下划线分隔。
staticconstintMAX_SIZE=64;
C++
成员变量
混合大小写,首字母小写。
protectedintmyHeight;
C,C++,Pro*C
变量
混合大小写,首字母小写。
intmyHeight;
表示变量作用域的前缀
平台
标识符作用域
前缀命名规则
例
C,C++,Pro*C
全局变量
g_
intg_iHeight;
C++
成员变量
m_
intm_iHeight;
C,C++,Pro*C
静态变量
s_
staticints_iHeight;
C,C++,Pro*C
局部变量
无
booleanbReturn;
C++
有类型常量
c_
constintc_iHeight=128;
表示变量数据类型的前缀
平台
变量数据类型
前缀命名规则
例
C,C++,Pro*C
byte
char
unsignedchar
c
charcEcho;
C,C++,Pro*C
short
WORD
w
shortwCount;
C,C++,Pro*C
int
i
intiRet;
C,C++,Pro*C
unsignedint
u
unsignedintuRet;
C,C++,Pro*C
long
DWORD
l
longlExcutionCount;
C++
__int64
QWORD
q
QWORDqBigRand;
C,C++,Pro*C
float
f
floatfClipTime;
C,C++,Pro*C
double
longdouble
d
doubledRadius;
C++
boolean
BOOL
b
booleanbReturn;
C,Pro*C
struct
t
struct_MyStructtMyStruct;
C,C++,Pro*C
struct
t
MyStructtMyStruct;
C++
数组
rg
DWORDrgArray[];
C++,LPC
Object(对象)
object
小写字母开头
CWndwindow;
objectob;
LPC
mixed
mapping
array
小写字母开头
mappingdbase;
string*ob;
C,C++,Pro*C
指针
p
void*pBuffer;
charpLine[C_LINE_LEN];
C,C++,Pro*C
char*,char[]
(见备注)
sz
char*szError;
charszDummy[C_LINE_LEN];
C++
CString
cs
CStringcsMessage;
C++
句柄:
HANDLE
unsignedvoid*
h
HWNDhWnd;
Pro*C
VARCHAR
v_
VARCHARv_cclmno[C_CLM_NO_LEN];
备注:
char*和char[]用作零结尾字符串时,以sz开头,仅用作缓冲区时,以p开头。
除非特别必要,不要使用short和byte类型,因为该类型可能比机器的字长要短,使线程无法并行优化,造成额外的运行周期。
char类型仅当使用做字符或做单字节位操作时使用。
对象类型的变量,应加上一定的识别标示,以帮助辨别是何种类型的对象。
VC中,自动生成的函数一般为大写开头,因此,在VC中可保持以大写开头的函数名。
文档和注释
程序代码内必须写注释。
文档和注释
注释的基本要素同总则所述,另外对于C,有如下建议:
尽量不要在编译器指示行上写注释,某些编译器会把带有“#”号的一整行当作编译器指令,而忽略后面的注释符号。
文件头注释
文件头注释的要素按照总则,需要包含文件名,文件功能,程序员全名,创建日期,项目名称,平台,编辑器,版权信息,修改记录等。
这是一个Unix下C程序的文件头例子:
/*
*NAME:
ClmService.pc
*FUNCTION:
处理请求数据包
*PROGRAMMED:
程序员全名
*DATE(ORG):
1994.94.14
*PROJECT:
项目名称
*OS:
所使用的操作系统
*Editor:
UltraEdit7.0
*History:
*NIDDATENOTE
*WGB1998.06.27初期作成
*PSZ2001.03.22修改SQLCA引用方式。
*/
其中History域的写法:
NID为程序员名称缩写,DATE为所做的修改的日期,NOTE为修改的内容,每一笔修改都必须在History域写明,当然,一个程序员在短期内连续不断的修改,可以只写一笔,但在描述中需把修改内容写清楚。
注释中可以增加若干“*”号或“-”号以隔开语段,*号的长度以不超过75个字符为宜。
例:
/*************************************************************************
*
************************************************************************/
//------------------------------------------------------------------------
对于VC生成的程序,可以系统生成的注释头为准,但自己写的函数和程序应注明函数头和文件头。
函数头注释
这是一个Unix下C语言函数头的例子,记录了如下的信息:
/*
*NAME:
函数名/函数原型
*FUNCTION:
函数功能
*PARAMETER:
输入参数及含义
*RETURN:
返回值
*EXTERN:
使用但未修改的全局变量及含义
*UPDATE:
修改的全局变量
*RETURN:
返回值及含义
*PROGRAMMED:
程序员简称
*DATE(ORG):
1994.04.14
*CALL:
调用的所有非C语言标准的函数列表,(既自定义的函数)
*MEMO:
有关描述和注释
:
*/
有关修改的注释
有关删除、修改、添加的注释可写为如下格式:
/*removedbyxxxxxon1994.12.20*/
/*addedbyxxxxxxon1994.10.09*/
/*modifiedbyxxxxon1996.01.07*/
文件组织
对源文件包含的下列几个部分给出定义:
头文件定义
包含的头文件以如下格式写出:
#include
其中,编译器指令后一定要加一个空格,include指令后的文件名如果是本目录下的文件就使用引号括起来,其余的都使用尖括号。
关于使用引号参数的include指令要严格控制,严禁在include指令内使用引号包含其他模块的私有头文件。
任何使用过的非本模块的函数,都必须指明其include文件,以确定其函数原型已正确声明。
变量定义:
全局变量不可以定义在头文件内,但头文件可以使用extern来声明使用全局变量。
任何生成实际代码的内容都不可以定义在头文件内,头文件应只包含:
●#define方式的常量定义。
●宏定义。
●函数原型声明。
●外部变量的extern声明。
●类型定义(struct和class)。
头文件不应包含:
●变量定义。
●函数实现。
代码风格
概述
代码风格以总则为基准。
括号
if和while之类的字句,尽可能把大括号写在单独的一行中。
即使只包含一句话,也尽量包含括号。
空的for和while语句也要尽量加括号。
续行
续行规则:
∙在『逗号,分号,』这些操作符后换行
∙在『』操作符前或之后换行
∙在『&&,||,』等逻辑操作符前换行
∙尽可能语意层次高的地方换行
下面是几个例子:
someMethod(longExpression1,longExpression2,longExpr3,
longExpression4,longExpression5);
var=someMethod1(longExpression1,
someMethod2(longExpression2,
longExpression3));
下面是运算符层次的例子:
longName1=longName2*(longName3+longName4-longName5)
+4*longname6;//推荐
longName1=longName2*(longName3+longName4
-longName5)+4*longname6;//避免
if语句的续行的例子:
//不建议使用此种缩进方式
if((condition1&&condition2)
||(condition3&&condition4)
||!
(condition5&&condition6)){//不恰当的缩进使得
doSomethingAboutIt();//这行容易被忽略或看错
}
//可以采用此方法(八格缩进)
if((condition1&&condition2)
||(condition3&&condition4)
||!
(condition5&&condition6)){
doSomethingAboutIt();
}
//建议采用此方法(两格缩进,括号单行,
//if语句的括号和条件之间加空格)
if((condition1&&condition2)
||(condition3&&condition4)
||!
(condition5&&condition6))
{
doSomethingAboutIt();
}
条件赋值操作符总是在操作符前续行,如:
alpha=(aLongBooleanExpression)?
beta:
gamma;
alpha=(aLongBooleanExpression)?
beta
:
gamma;
alpha=(aLongBooleanExpression)
?
beta
:
gamma;
并列语句操作符(逗号)需要尽量写在一行,以免与分号混淆:
i=ia+ib,i>ic;
空格
空格可遵循如下规则:
∙关键字(如switch,case,return,sizeof,while,if,else)后加一个空格:
while(true){
...
}
return(a
1:
0;
注意:
因为对于函数调用来说,函数名和参数表的括号之间不可以加空格。
因此这种写法可以帮助区别函数调用和保留字。
∙在函数参数表内,每个逗号后应当跟一个空格。
例
sprintf(szTemp,"sizeis%d%f%s",iRet,fMutiply,szConcat);
∙除了句点”.”以外,所有的二元操作符与操作对象之间都必须用空格隔开,所有的单元操作符例如负号、增量减量符号(“++”,”--“)与操作对象之间不可以加空格,例:
a+=c+d;
a=(a+b)/(c*d);
while(d++=s++){
n++;
}
printSize("sizeis"+foo+"\n");
∙for语句的每个语段后面需加一个空格,例:
for(expr1;expr2;expr3)
∙强制类型转换建议加空格,例:
myMethod((byte)aNum,(Object)x);
myMethod((int)(cp+5),((int)(i+3))
特定的结构
switch语句的结构:
/*
*comments
*/
switch(ch){
/*comment*/
caseTAB:
statements;
break;
/*comment*/
default:
statements;
break;
}
要点:
case语句的缩进与switch语句相同,case语句下缩进四个空格。
if…else语句的结构:
/*comments*/
if(condition)
{
/*comment*/
statements;
}elseif(condition)
{
/*comment*/
statements;
}else
{
/*comment*/
statements;
}
要点:
else语句写在if语句的回括号上,以便确定对应的if语句。
UnixC中函数定义的格式
voidfunc(intix,structT1*ty,unionU1*tz)
{
/*comment*/
intip;
/*comment*/
statements;
return;
}
要点:
没有返回值函数,一定要写void头。
函数尾一定要写return语句。
条件编译指令不可以破坏括号的匹配,例:
/*这个方法会导致有两个“{”,却只有一个“}”。
所以会造成某些编缉器报错*/
#ifdefNO_VERSION_INFO
if(strcmp(szVersionInfo,APP_VERSION)!
=0){
#else
szMyVersion=getProfileString(szMyVersion,"Version");
if(!
szMyVersion)
returnnotify_fail("Versionconfignotfound!
");
if(strcmp(szVersionInfo,szMyVersion)!
=0){
#endif
statements;
}
/*在条件编译指令里面只能包含成对的“{”,“}”。
或者不包含括号*/
#ifdefNO_VERSION_INFO
if(strcmp(szVersionInfo,APP_VERSION)!
=0)
#else
szMyVersion=getProfileString(szMyVersion,"Version");
if(!
szMyVersion)
returnnotify_fail("Versionconfignotfound!
");
if(strcmp(szVersionInfo,szMyVersion)!
=0)
#endif
{
statements;
}
有关临时的修改
临时的修改可使用以下格式:
/*?
?
?
modifiedbyxxxxon1995.02.20*/
#if0
//修改前的段落
#else
//修改后的段落
#endif
不过,请注意,0是一个无效的编译器指令,只可以临时使用,待该代码调试通过后,可把原代码删除或者定义一个有效的编译器指令。
如:
/*modifiedbyxxxxxbefore1995.03.01*/
修改后的段落
/*orignalcodehasbeenremoved!
*/
或者:
/*modifiedbyxxxxon1995.02.20*/
#ifdefNO_CHECK_PLY_FLAG
修改前的段落
#else
修改后的段落
#endif
范例型条件编译指令
DEBUG指令
在Unix下,使用printf语句等语句进行调试时,调试语句可写在
#ifdefDEBUG和#endif之间,这样,只需简单地改变编译命令行参数就可以删除或使用调试语句。
在Windows下,应使用#ifdef_DEBUG宏。
程序实现
恰当的访问权限
本节是有关C++的。
仅仅将实现已对外公布其功能的函数或类才声明为public。
如果需要在类之外使用,常量可以被定义为public。
除非该对象仅仅执行基本的数据结构的功能,对象的实例变量绝不应该定义为public,如果需要快速访问该变量,可以考虑定义get函数。
除非有必要在子类重载,仅在类成员函数里用到的变量和方法应当声明为private。
通常,只有非常巧妙的扩展才确实有效,因此多数此类变量和方法都应定义为private,否则定义为protected。
常量
不要直接书写数字类型常量,(除了小整数,如:
-1,0,1)。
C++使用staticconst常量代替,C语言可用宏定义#define代替。
静态成员引用
C++中,在定义之外调用静态类的成员,使用类名而不使用对象名,否则会引起混淆。
例:
AClass.CLASS_METH();//OK
randomObj.CLASS_METHOD();//AVOID
不要隐藏变量
不要定义一个与局外变量同名的变量,这样覆盖外部变量往往会使程序的可读性降低。
声明
一行只写一个声明:
intv1,v2;//WRONG
intv1;
intv2;//RIGHT
只在作用域开头定义变量,除了下面一种情况,可以定义在循环体开头:
for(inti=0;i 赋值 不要在易混淆的地方使用赋值操作符 if(c++=d++) {//AVOID! ... } 应写为 if((c++=d++)! =0) { ... } 不要为了改善运行效率而使用复合式赋值语句,这是编译器的任务。 例: d=(a=b+c)+r;//AVOID! 应写为 a=b+c; d=a+r; 括号 通常在混合的操作符之间加括号是一个比较好的习惯。 即使你对运算符优先级很熟,但你不应假设他人对运算符的了解程度也和你完全相同。 if(a==b&&c==d)//AVOID! if((a==b)&&(c==d))//RIGHT 在三元操作符的”? ”之前如果有二元表达式,应该加括号。 例: (x>=0)? x: -x; 返回值 使程序和你的意图相同。 例: if(booleanExpression) { returntrue; }else { returnfalse; } 应当写为 returnbooleanExpression; 类似地 if(condition) { returnx; } returny; 应当写成: return(condition? x: y); 内存分配的处理 { char*szItName=NULL;//定义指针必须赋初值 szItName=(char*)malloc(...); if(szItName==NULL)//这里必须加上返回值校验 ... ... //先校对后释放 if(szItName) free(szItName); } 对于函数传入的参数,如果是指针,一定要校对其是否为NULL; voidfunc(char*p) { if(p==NULL){ ... } ... return; } 对于返回指针的函数,一定要弄清该指针由谁负责释放,如果由调用者释放,则需要保存该值。 例: //错误 if(GetWindowsDirectory(WindowsDir,MAX_PATH)==MY_DIR) ... //正确 szWindowsDir=GetWindowsDirectory(WindowsDir,MAX_PATH); if(szWindowsDir==MY_DIR) ... free(szWindowsDir); 其他 关于宏定义: 建议C++程序中不使用宏定义,而一律采用内联(inline)函数。 这样做的好处是: 在跟踪程序运行时,可以跟踪进入内联函数,而不能进入宏定义中。 值得指出的是: 内联函数应尽可能的小。 在Pro*C程序中,不要定义与Oracle保留字相同的变量: 如user,sysdate,c
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编程 规范 CPP