C++编码规范最新版本.docx
《C++编码规范最新版本.docx》由会员分享,可在线阅读,更多相关《C++编码规范最新版本.docx(17页珍藏版)》请在冰豆网上搜索。
C++编码规范最新版本
文件编号:
密级:
内部
版本:
V1.0
C++编码规范
共16页
二〇一七年四月
修订状态页
文件名称
C++编码规范
文件编号
版本
V1.0
日期
2017-04-06
更改章节
更改内容
更改页码
更改日期
更改人
备注:
1前言
本指南的目的是通过详细阐述在C++编码时要怎样写、不要怎样写来规避其复杂性。
这些规则可在允许代码有效使用C++语言特性的同时使其易于管理。
2程序布局
2.1头文件结构
头文件通常由以下几部分组成:
a)头文件注释:
为方便维护,头文件和实现文件需加文件头,头文件由版权声明、文件名内容摘要、操作三部分内容组成
b)预处理快:
为了防止头文件被重复引用,应当用ifndef/define/endif结构产生预处理块,命名格式:
[文件名全大写]_H__,如
#ifndefMYGLOBAL_H__
c)文件引用:
文件引用顺序依次为C标准库、C++标准库、外部模块、内部模块,注意尽量减少在头文件中#include的数量
d)类、结构、枚举等声明
2.2实现文件
实现文件通常由以下几部分组成
a)文件引用:
文件引用顺序依次为预编译头文件引用、配套头文件引用、C标准库、C++标准库、外部模块、内部模块预编译头文件引用。
b)程序实现体:
数据和函数的定义,按照头文件定义顺序进行实现。
3命名规则
好的命名规则能极大地增加可读性和可维护性。
同时,对于一个有上百个人共同完成的大项目来说,统一命名约定也是一项必不可少的内容。
本章对程序中的所有标识符(包括变量名、常量名、函数名、类名、结构名、宏定义等)的命名做出约定。
3.1文件
文件名称由一个或多个单词构成。
为便于界定,每个单词的首字母要大写。
文件名称一定要能确切的表达文件的内容,禁止使用过于泛的名称,如用户管理对话框不应该命名为User.h 而应该命名为UserManageDlg.h。
3.2类/结构
a)C++类/结构的命名:
类的名称由一个或多个单词构成。
为便于界定,每个单词的首字母要大写。
b)推荐的组成形:
类的命名推荐用“前缀”+"名词"或"形容词+名词"的形式,例如:
"GAnalyzer","CFastVector"....前缀为了区分不同的工程或者模块,例如MFC的CString,QT的QString,GIS中的GObject,目前本公司采用My开头,如MyString。
3.3函数
a)命名规则:
函数的名称由一个或多个单词组成,首字母小写,其余每个单词的首字母要大写。
私有函数名称前加下划线。
b)组成形式:
函数名应当使用"动词"或者"动词+名词"(动宾词组)的形式。
例如:
"getName()","getValue()","erase()","reserve()"....
c)对于bool值获取和设置的函数采用如下格式:
voidsetModified(bool bModified);
boolisModified();
d)针对QT的特别说明:
Qt下slot函数统一采用on_作为前缀,如:
on_MouseButtonClicked();
3.4变量
a)变量的命名:
变量名由作用域前缀+类型前缀+一个或多个单词组成。
为便于界定,每个单词的首字母要大写。
对于某些用途简单明了的局部变量,也可以使用简化的方式,如:
i,j,k,x,y,z....
b)作用域前缀:
作用域前缀标明一个变量的可见范围。
作用域可以有如下几种:
m_:
类的成员变量(member)
ms_:
类的静态成员变量(staticmember)
s_:
静态变量(static)
g_:
普通全局变量(global)
gs_:
静态全局变量(staticglobal)
gg_:
进程或动态链接库中的全局变量(globalglobal)
除非不得已,否则应该尽可能少使用全局变量。
c)类型前缀:
类型前缀标明一个变量的类型,主要类型如下:
i:
整形(int)可以下面n表示
n:
整型和位域变量(number)
以“n”作为所有整形前缀是由于大多数情况下,编写程序时不需要过多考虑整形的宽度,但在某些场合中,整形宽度是需要特别注意并且仔细加以区分的,这时可使用如下记法代替“n”前缀:
uc:
字节(8bit,unsignedchar,byte)
w:
字(16bit,word)
dw:
双字(32bit,doubleword)
nn:
四字(64bit,quadword)
bf:
位域(bitfield)
对浮点型变量也有类似记法如下:
f:
单精度浮点(32bit,float)
d:
双精度浮点(64bit,double)
ld:
扩展精度浮点(80bit,longdouble)
e:
枚举型变量
c:
char
sz:
传统的C字符串(char*,char[])
str:
字符串(std:
:
string)
map:
键值容器(std:
:
map)
lis:
动态数组(std:
:
list)
vec:
动态数组(std:
:
vector)
deq:
双端队列(std:
:
deque)
p:
指针
b:
bool
h:
HANDLE
us:
结构类型/联合
类型前缀可以组合使用。
d)推荐的组成形式:
变量的名字应当使用"名词"或者"形容词+名词"。
例如:
"nCode","m_nState","nMaxWidth"....
3.5常量、宏
名称统一使用大写,标识符必须指示常量具体含义,单词间通过下划线来界定。
如:
ERROR_UNKNOWN,OP_STOP
3.6结构体
结构体使用typedefstruct并以tag_开头,后命名规则同类。
如:
typedefstructtag_History
{
charszName[32];
intiIndex;
}History;
3.7枚举
命名规则同内,枚举值采用枚举名缩写并采用小写开头。
如
enumEquipmentPart
{
epSamplePin=0,
epRea1Pin=2,
epRea2Pin=4
};
4代码风格与板式
代码风格的重要性怎么强调都不过分。
一段稍长一点的无格式代码基本上就是不可读的。
先来看一下这方面的整体原则:
4.1空行的使用
空行起着分隔程序段落的作用。
空行得体(不过多也不过少)将使程序的布局更加清晰。
空行不会浪费内存,虽然打印含有空行的程序是会多消耗一些纸张,但是值得。
所以不要舍不得用空行。
●在每个类声明之后、每个函数定义结束之后都要加2行空行。
●在一个函数体内,逻揖上密切相关的语句之间不加空行,其它地方应加空行分隔。
4.2语句与代码行
一行代码只做一件事情,如只定义一个变量,或只写一条语句。
这样的代码容易阅读,并且方便于写注释。
"if"、"for"、"while"、"do"、"try"、"catch"等语句自占一行,执行语句不得紧跟其后。
不论执行语句有多少都要加"{}"。
这样可以防止书写和修改代码时出现失误。
4.3缩进和对齐
程序的分界符"{"和"}"应独占一行并且位于同一列,同时与引用它们的语句左对齐。
"{}"之内的代码块在"{"右边一个制表符(4个半角空格符)处左对齐。
如果出现嵌套的"{}",则使用缩进对齐。
如果一条语句会对其后的多条语句产生影响的话,应该只对该语句做半缩进(2个半角空格符),以突出该语句。
4.4最大长度
代码行最大长度宜控制在70至100个字符以内。
代码行不要过长,否则眼睛看不过来,也不便于打印(2009年更新:
随着GUI开发环境和高分宽屏的普及,此规则可以视情况适当放宽)。
4.5长行拆分
长表达式要在低优先级操作符处拆分成新行,操作符放在新行之首(以便突出操作符)。
拆分出的新行要进行适当的缩进,使排版整齐,语句可读。
例如:
if((very_longer_variable1>=very_longer_variable2)
&&(very_longer_variable3<=very_longer_variable4)
&&(very_longer_variable5<=very_longer_variable6))
{
...
}
4.6空格的使用
关键字之后要留空格。
象"const"、"virtual"、"inline"、"case"等关键字之后至少要留一个空格,否则无法辨析关键字。
象"if"、"for"、"while"、"catch"等关键字之后应留一个空格再跟左括号"(",以突出关键字。
函数名之后不要留空格,紧跟左括号"(",以与关键字区别。
"("向后紧跟。
而")"、","、";"向前紧跟,紧跟处不留空格。
","之后要留空格,如Function(x,y,z)。
如果";"不是一行的结束符号,其后要留空格,如for(initialization;condition;update)。
赋值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符,如"="、"+="">="、"<="、"+"、"*"、"%"、"&&"、"||"、"<<","^"等二元操作符的前后应当加空格。
一元操作符如"!
"、"~"、"++"、"--"、"&"(地址运算符)等前后不加空格。
象"[]"、"."、"->"这类操作符前后不加空格。
对于表达式比较长的for、do、while、switch语句和if语句,为了紧凑起见可以适当地去掉一些空格,如for(i=0;i<10;i++)和if((a<=b)&&(c<=d))
例如:
voidFunc1(intx,inty,intz);//良好的风格
voidFunc1(intx,inty,intz);//不良的风格
//===========================================================
if(year>=2000)//良好的风格
if(year>=2000)//不良的风格
if((a>=b)&&(c<=d))//良好的风格
if(a>=b&&c<=d)//不良的风格
//===========================================================
for(inti=0;i<10;i++)//良好的风格
for(inti=0;i<10;i++)//不良的风格
for(inti=0;i<10;i++)//过多的空格
//===========================================================
x=a
a:
b;//良好的风格
x=a
a:
b;//不好的风格
//===========================================================
int*x=&y;//良好的风格
int*x=&y;//不良的风格
intiX=-1;//良好的风格
intiX=-1;//不良的风格
//===========================================================
array[5]=0;//不要写成array[5]=0;
a.Function();//不要写成a.Function();
b->Function();//不要写成b->Function();
4.7修饰符的位置
为便于理解,应当将修饰符"*"和"&"紧靠数据类型。
例如:
char*pName;
int*piX;
intiY;//为避免y被误解为指针,这里必须分行写。
int*Function(void*p);
4.8与常量的比较
在与宏、常量进行"==","!
=",">=","<="等比较运算时,应当将常量写在运算符左边,而变量写在运算符右边。
这样可以避免因为偶然写错把比较运算变成了赋值运算的问题。
例如:
if(NULL==p)//如果把"=="错打成"=",编译器就会报错
{
//...
}
4.9类排版
类主要包括构造函数析构函数自定义函数,变量组成:
//版权注释......
#ifndefMYDEMO_H__//防止重复包含
#defineMYDEMO_H__//防止重复包含
//库引用尽量少,能放入实现中放入实现,特别针对动态库的封装
//内注释......
classMyDemo
{
public:
//如有枚举放在最前面
//构造析构函数放在第二
//一般函数
private:
//一般私有函数
public:
//变量定义放在后面
private:
//私有变量定义放在最后
};
#endif//MYDEMO_H__//防止重复包含保护宏结尾
4.10注释
4.10.1头文件注释
头文件需加文件头,头文件由版权声明、文件名内容摘要、操作三部分内容组成:
/**
*Copyright(c)2011,
*Allrightsreserved.
*
*@filefile.h
*@brief概要说明
*详细说明
*@author作者@versionV1.0@date2016-04-26
*
*/
4.10.2类头注释
/**
*@class类名
*@brief概要说明
*详细说明
*@author作者@versionV1.0@date2016-04-26
*/
或者
/**说明*/
4.10.3变量注释
类、结构体、枚举变量采用如下三种形式:
/**第一种在变量上面说明*/
intm_iRemove;
/**
*第二种
*在变量上面多行说明
*/
intm_iRemove;
intm_iRemove;//!
<第三种在变量右边说明
4.10.4函数注释
/**
*函数说明
*@param变量名称变量说明
*@returnvoid返回值说明
*/
4.10.5实现体内注释
注释的位置应与被描述的代码相邻,可以放在代码的上方或右方,不可放在下方。
边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。
不再有用的注释要删除。
注释应当准确、易懂,防止注释有二义性。
错误的注释不但无益反而有害。
当代码比较长,特别是有多重嵌套时,应当在一些段落的结束处加注释,便于阅读。
5代码示例
头文件示例:
/**
*Copyright(c)2017,
*Allrightsreserved.
*
*@fileMyDemo.h
*完整的代码示例
*
*@authorXXX@versionV1.0@date2017-04-06
*
*/
#ifndefMYDEMO_H__//防止重复包含
#defineMYDEMO_H__//防止重复包含
//库引用尽量少,能放入实现中放入实现,特别针对动态库的封装
#include//C标准库引用
#include//C++标准库引用
#include"MyHelper.h"//外部库引用
#include"MyGlobal.h"//内部引用
/**枚举说明*/
enumEquipmentPart
{
epSamplePin=0,//!
<枚举值说明
epRea1Pin=2,//!
<枚举值说明
epRea2Pin=4//!
<枚举值说明
};
/**结构体说明*/
typedefstructtag_History
{
charszName[32];//!
<结果体变量说明
intiIndex;//!
<结果体变量说明
}History;//!
<结构体说明
classMyDemoManage;//内使用前声明,尽量不采用#include引用,在CPP中引用。
/**
*@classMyDemo
*@brief内注解
*
*@authorauthor@versionV1.0@date2017-04-06
*/
classMyDemo
{
public:
MyDemo();
~MyDemo();
/**函数1*/
voidTest();
/**
*函数2
*@returnint返回值说明
*/
intgetTest1();
private:
/**
*函数说明
*@paramiValue参数1说明
*@paramiV2参数2说明
*@returnint返回值说明
*/
int_setTest1(intiValue,intiV2);
public:
/**变量说明*/
intm_iTest1;
private:
doublem_dTest2;//!
<变量说明
floatm_fTest3;//!
<变量说明
std:
:
stringm_strTest4;//!
<变量说明
std:
:
vectorm_vecTest5s;//!
<变量说明
MyDemoManage*m_pDemoManage;//!
<变量说明
};
#endif//MYDEMO_H__//防止重复包含保护红结尾
实现文件示例:
/**
*Copyright(c)2017
*Allrightsreserved.
*
*@fileMyDemo.cpp
*完整的代码示例实现
*
*@authorXXX@versionV1.0@date2017-04-06
*
*/
#include"stdafx.h"//预处理头放在开始
#include"MyDemo.h"//关联头放在第二位
#include//C标准库引用
#include//C++标准库引用
#include"MyHelper.h"//外部库引用
#include"MyGlobal.h"//内部引用
MyDemo:
:
MyDemo()
{
//整形、布尔、指针、浮点等必须初始化
m_iTest1=0;//注释
m_dTest2=0.0f;//注释
m_fTest3=0.0f;//注释
m_pDemoManage=nullptr;//nullptr为C++11标准空指针写法,开发环境在VS2013或者GCC4.8以上使用
}
MyDemo:
:
~MyDemo()
{
}
/**函数1*/
voidMyDemo:
:
Test()
{
Historyhistory;//局部变量注解
intiW=0;//局部变量注解
//实现XXX
if((iW>0)&&(iW<100))
{
if(m_pDemoManage!
=nullptr)//指针使用前必须判断空,C++11标准
{
}
if(NULL!
=m_pDemoManage)//指针使用前必须判断空,老标准
{
}
}
}
/**
*函数2
*@returnvoid返回值说明
*/
intMyDemo:
:
getTest1()
{
}
/**
*函数说明
*@paramiValue参数1说明
*@paramiV2参数2说明
*@returnint返回值说明
*/
intMyDemo:
:
_setTest1(intiValue,intiV2)
{
switch(iValue)
{
case1:
{
//实现中尽量加上{}作用域范围,避免在其中定义临时变量无法编译。
}
break;
default:
{
//使用switch需实现default:
默认
}
break;
}
}
(此文档部分内容来源于网络,如有侵权请告知删除,文档可自行编辑修改内容,供参考,感谢您的配合和支持)