

下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、C+语言编程标准Copyright 袞:XXX 技术有限公司C+代码规范版本历史版本/状态作者参与者起止日期备注V 1.0周国飞2003-4-15至2004-22周国飞起草C+语言编程标准Copyright 袞:XXX 技术有限公司目录1.介绍.12.编码规范.22.1 文件结构. 22.1.1 版权和版本的声明.22.1.2 头文件的结构 .22.1.3 定义文件的结构.32.1.4 目录结构.42.2 结构化程序设计 .42.2.1 功能模块抽取.42.2.2 功能模块编码原则 .52.2.3 编程标准.62.2.4 源代码层次.62.3 命名约定. 72.3.1 综述. 72.3.2 变
2、量命名.82.3.3 函数及数组的命名.92.3.4 结构类型命名 .102.3.5 命名长度.102.3.6 Windows 应用程序命名规则 . 102.4 程序规则.122.4.1 变量声明和定义.122.4.2 数组、字符串 .132.4.3 函数声明和定义 .142.4.4 语句.162.5 排版格式规则 .162.5.1 源代码文件 .172.5.2 空行.172.5.3 代码行.172.5.4 代码行内的空格 .182.5.5 对齐.192.5.6 分行.202.5.7 表达式.202.5.8 函数.222.5.9 语句.222.5.10 变量、类型声明 .232.5.11 修饰
3、符的位置 . 232.5.12 类的版式 . 242.6 注释格式.242.6.1 介绍.242.6.2 注释基本规则 .25C+语言编程标准Copyright 袞:XXX 技术有限公司2.6.3 程序注释.252.6.4 模块注释.26C+语言编程标准Copyright 袞:XXX 技术有限公司265 函数注释273.代码管理.错误!未定义书签3.1 版本管理.613.2 代码更新.61C+语言编程规范Copyright 王:中兴信息技术有限公司第1页共 71 页1.介绍本文的宗旨在于规范化源代码的编写,满足系统面向对象要求、可读性要 求、正确性与容错性要求和可重用性要求。适用范围:本文档描
4、述C+语言编程规范,适用于公司所有C+程序的编制C#语言编程规范Copyright 王:中兴信息技术有限公司第2页共 71 页2. 编码规范2.1 文件结构每个C+/C程序通常分为两个文件。一个文件用于保存程序的声明(declaration), 称为头文件。另一个文件用于保存程序的实现 (implementation),称为定义(definition) 文件。C+/C程序的头文件以“.h”或”.hpp”为后缀,C程序的定义文件以“.c”为后缀,C+程序的定义文件通常以“.cpp”为后缀(也有一些系统以“.cc”或“.cxx”为后缀)。2.1.1 版权和版本的声明版权和版本的声明位于头文件和定义
5、文件的开头(参见示例2-1),主要内容有:(1)版权信息。(2)文件名称,标识符,摘要。(3)当前版本号,作者/修改者,完成日期。(4)版本历史信息。/文件名称:CommServer.h in terface of the CommServer class摘要:简要描述本文件的内容/ Copyright (c) 2002-2003,深圳中心信息技术有限公司技术开发部/All rights reserved./程序注释:服务端TCP连接组件,监听客户端的连接,维护物理链路,/提供数据操作方法/当前版本:1.5作者:输入作者(或修改者)名字/完成日期:2003年5月20日/取代版本:1.0/原作者
6、:输入原作者(或修改者)名字/完成日期:2002年9月10日/示例 2-1 版权和版本的声明2.1.2 头文件的结构头文件由三部分内容组成:(1)头文件开头处的版权和版本声明(参见示例2-1)。C#语言编程规范Copyright 王:中兴信息技术有限公司第3页共 71 页(2)预处理块。C#语言编程规范Copyright 王:中兴信息技术有限公司第4页共 71 页(3)函数和类结构声明等。假设头文件名称为CommServer.h,头文件的结构参见示例2-2。为了防止头文件被重复引用,应当用ifndef/define/endif结构产生预处理块。用#inelude 格式来引用标准库的头文件(编译
7、器将从标准库目录开始搜 索)。用#include CommServer.h格式来引用非标准库的头文件(编译器将从用户的工作 目录开始搜索)。头文件中只存放“声明”而不存放“定义”在C+语法中,类的成员函数可以在声明的同时被定义,并且自动成为内联函数。这 虽然会带来书写上的方便,但却造成了风格不一致,弊大于利。建议将成员函数的定义与声 明分开,不论该函数体有多么小。不提倡使用全局变量,尽量不要在头文件中出现象extern int nConectNum这类声明。示例 2-2 C+/C 头文件的结构2.1.3 定义文件的结构定义文件有三部分内容:(1)定义文件开头处的版权和版本声明(参见示例2-1)
8、(2)对一些头文件的引用。(3)程序的实现体(包括数据和代码)。假设定义文件的名称为CommServer.cpp,定义文件的结构参见示例2-3。/版权和版本声明见示例2-1,此处省略。/#include stdafx.h/引用头文件#includeCommServer.h”#include TradeCenter.h#include TradeCenterDoc.h#i nclude TradeCe nterView.h版权和版本声明见示例2-1,此处省略。COMMSERVER_H /防止CommServer.h被重复引用COMMSERVER_H/#ifndef#defi ne#i nclud
9、e #includeCommPublic.h”void Function1();class CommServer;/引用标准库的头文件/引用非标准库的头文件/全局函数声明/类结构声明C#语言编程规范Copyright 王:中兴信息技术有限公司第5页共 71 页#i nclude Mai nF rm.h/全局函数的实现体void Function1()/类成员函数的实现体void CommServer:HandleDataBody ()示例 2-3 C+/C 定义文件的结构2.1.4 目录结构如果一个软件的头文件数目比较多(如超过十个),通常应将头文件和定义文件分别保存于不同的目录,以便于维护。
10、例如可将头文件保存于include目录,将定义文件保存于source目录(可以是多级目 录)。如果某些头文件是私有的,它不会被用户的程序直接引用,则没有必要公开其“声 明”。为了加强信息隐藏,这些私有的头文件可以和定义文件存放于同一个目录。2.2 结构化程序设计2.2.1 功能模块抽取模块划分是结构化程序设计最重要的手段,应遵循以下原则: 在模块中必须保证可预知的运行顺序。 可重用代码尽量抽取出来形成函数。函数设计时尽量追求使用简明的逻辑,可以牺牲少许计算复杂度以使逻 辑简单。尽量多的使用公用模块。公用模块由单独的人员负责编制,避免多人编制。 每个函数,都有函数头说明,详见函数说明模板。不同的
11、功能模块尽量放在不同的文件中,便于管理。禁用语句:用if语句来强调只执行两组语句中的一组。禁止else goto和elsereturn嵌套限制:禁止超过三重的嵌套语句C#语言编程规范Copyright 王:中兴信息技术有限公司第6页共 71 页2.2.2 功能模块编码原则当编写过程、函数时,必须遵循以下原则:1.基本要求程序结构清析,简单易懂,单个函数的程序行数不得超过200行。打算干什么,要简单,直接了当,代码精简,避免垃圾程 序。尽量使用标准库函数和公共函数。使用括号以避免二义性。2.可读性要求可读性第一,效率第二。保持注释与代码完全一致。每个源程序文件,都有文件头说明,说明规格见规范。每
12、个函数,都有函数头说明,说明规格见规范。主要变量(结构、联合、类或对象)定义或引用时,注释 能反映其含义。常量定义有相应说明。处理过程的每个阶段都有相关注释说明。在典型算法前都有注释。利用缩进来显示程序的逻辑结构,缩进量一致并以Tab键 为单位,定义Tab为4个字节。循环、分支层次不要超过三层。注释可以与语句在同一行,也可以在上行。 空行和空白字符也是一种特殊注释。一目了然的语句不加注释。注释的作用范围可以为:定义、引用、条件分支以及一段 代码。避免不必要的分支。3.结构化要求禁止出现两条等价的支路。尽是少用goto语句。用if语句来强调只执行两组语句中的一组。禁止elsegoto和else
13、return用case实现多路分支。避免从循环引出多个出口。函数只有一个出口。不使用条件赋值语句。避免不必要的分支。不要轻易用条件分支去替换逻辑表达式4.正确性与容错性要求程序首先是正确,其次是优美无法证明你的程序没有错误,因此在编写完一段程序后,应先回头检查。改一个错误时可能产生新的错误,因此在修改前首先考虑 对其它程序的影响。所有变量在调用前必须被初始化。C#语言编程规范Copyright 王:中兴信息技术有限公司第7页共 71 页对所有的用户输入,必须进行合法性检查。每个函数开始, 必须有对输入参数的检查过程。不要比较浮点数的相等,如:10.0 * 0.1 = 1.0,不可靠程序与环境或
14、状态发生关系时,必须主动去处理发生的意 外事件,如文件能否逻辑锁定、打印机是否联机等。单元测试也是编程的一部份,提交联调测试的程序必须通 过单元测试。函数应有尽量少的出口调用return语句显式返回。(对于main()用exit()。尽量减少多点返回。函数要尽量避免布尔型参数。5.可重用性要求重复使用的完成相对独立功能的算法或代码应抽象为公 共控件或类。公共控件或类应考虑00思想,减少外界联系,考虑独立 性或封装性。公共控件或类应建立使用模板。2.2.3 编程标准遵循C+标准语法 最重要的目标是程序的可读性和可维护性。一个程序有唯一的出口和入口。 不要存在有多个退出程序的出口 尽量简化main
15、(),不要超过60行.2.2.4 源代码层次按照以下要求组织源代码:程序注释模块注释引用系统头文件引用项目头文件引用本程序头文件常量宏参数宏函数定义和实现如果仅仅是本模块调用的函数,则应该定义为私有的成员函数。只有那些由本程序内部多个模块之间调用的函数定义为公有的成 员函数,类的成员变量尽量使用私有的成员变量。函数声明的顺 序如下:构造函数引用项目头文件引用本程序头文件常量宏参数宏 固有类型声明(指针、数组等,typedef longLongArrMacMaxNumber)复杂类型定义(结构、联合等typedef stuct date recDate函数声明:所C#语言编程规范Copyrigh
16、t 王:中兴信息技术有限公司第8页共 71 页有要使用的函数都要先声明后使用。如果一个 函数未在头文件中声明,则必须在本程序中完成。如果仅仅是本模块调用的函数,则应该只在本模块源代码内部定 义。只有那些由本程序内部多个模块调用的函数放在全程变量区 声名。函数声明的顺序如下:构造函数main()(如果存在).高层函数定义,如初始化函数、主处理函数、结束函数 底层函数定义,要符合一个从低到高的逻辑。2.3 命名约定2.3.1 综述没有一种命名规则可以让所有的程序员赞同,本文档论述的共性规则是被大多数程序员采纳的,我们应当在遵循这些共性规则的前提下,再扩充特定的规则使用C+创建任何标识时遵循下列规则
17、:标识符应当直观且可以拼读,可望文知意,不必进行“解码”。标识符最好采用英文单词或其组合,便于记忆和阅读。切忌使用汉语拼音 来命名。程序中的英文单词一般不会太复杂,用词应当准确。例如不要把CurrentValue写成NowValue。使用描述性的、有意义的标识。以种类开始,然后是种类属性。例如,使用strUserName而不是strNameUse。避免使用一般化的单词,例如Value,Number。命名规则尽量与所采用的操作系统或开发工具的风格保持一致。例如Windows应用程序的标识符通常采用大小写”混排的方式,如AddUser。而Unix应用程序的标识符通常采用“小写加下划线”的方式,如a
18、dd_user。别把这两类风格混在一起用。程序中不要出现仅靠大小写区分的相似的标识符。例如:int n, N;/变量n与N容易混淆void close(int x);/函数close与CLOSE容易混淆void CLOSE(float x);用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。 例如:int mi nV alue; int maxValue;int SetUserName();int GetUserName();C#语言编程规范Copyright 王:中兴信息技术有限公司第9页共 71 页常量、预处理宏名字中的所有字母都应大写,中间可以用_分隔,即使用xxx_xxx格式。
19、常量宏、变量宏的定义都用这种方法。例如:con st int MAX = 100;con st int MAX_LENGTH = 100;#define MAX_PATH 256#define PI 3.1415926类名、结构名、枚举名一律按XxxXxxXXX格式书写,如ChangeConfig。尽量避免名字中出现数字编号,如Value1,Value2等,除非逻辑上的确需要编号。这是为了防止程序员偷懒,不肯为命名动脑筋而导致产生无意义的名字(因为用数字编号最省事)。2.3.2 变量命名不要在变量首位用下划线,因为这与系统冲突。程序中的变量尽量不使 用下划线,变量中有意义的部分用大小写区分。程
20、序中不要出现标识符完全相同的局部变量和全局变量,尽管两者的作用域不同而不会发生语法错误,但会使人误解。变量和参数用小写字母开头的单词组合而成。例如:BOOL bSuccess;int n SelectType;变量的名字应当使用“名词”或者“形容词+名词”C#语言编程规范Copyright 王:中兴信息技术有限公司第10页共 71 页例如:stri ngstrFileName;floatfOldV alue;floatfNewValue;recDate rCurre ntDate; /*/对于变量的命名,除了要求在变量名中加入前缀使变量的类型一目了然之外,我们应在前缀之后的描述中表明该变量在程
21、序中的作用。2.3.3 函数及数组的命名函数及数组的命名遵循与变量的命名大体同样的约定,名字由相应的返 回类型名开始,后跟一个描述的标签。但是,函数如果可以明确断定归属于某 个模块,应该在类型描述后加模块名.类名和函数名用大写字母开头的单词组合而成。例如:class Node;/类名class LeafNode;/类名void Draw(void);/函数名void SetValue(i nt value);/函数名循环变量可以使用单个小写字母来命名。例如:for(int i = 0; i Draw();/类的成员函数在数组的命名中在类型名之后加一数字以表示数组的维数。 例如:char chL
22、astKeyPressed; /*字符变量*/char chinputBuffer; /*字符数组*/char chReadKeyBoard(); /*返回字符类型的函数*/int nCfgReadKeyBoard();/*归属于Cfg模块的返回字符类型的函 数*/2.3.4 结构类型命名结构名加前缀rec,枚举类型加前缀enu,对象名前加obj。例如:struct_RecDate _public int nY ear;public int nMon th;public int n Day;class ObjSetenumEn uPayme ntTypeHouse = 110,/房款Handl
23、ingCharge = 120,/手续费Agency = 130,/代理费;2.3.5 命名长度变量名(函数名,过程名)最小长度符合以下规则除了特例,要大于5个字符(特例包括n , m, i , j表示整数) 满足最大规则的前提下尽量使变量名短小建议最大不超过31个.保证external function前6个字符在系统中是唯一的.2.3.6 Windows 应用程序命名规则本文档对“匈牙利”命名规则做了合理的简化,下述的命名规则简单易用适用于Windows应用软件的开发。前缀类型描述例子C#语言编程规范Copyright 王:中兴信息技术有限公司第12页共 71 页gglobal全局变量in
24、t g nHowManyPeopleCClass orstructure类或结构CDocume nt, CPrintlnfoC#语言编程规范Copyright 王:中兴信息技术有限公司第13页共 71 页m_C+ class datamemberC+类的数据成员,这样可以避 免数据成员与成员函数的参数 同名。int m_n Width;CDocument* m_pDoc;sstatic静态变量加前缀s表示staticstatic int s nlni tValue;chchar8位字符或字符串charchLastKeyPressed;char chBuffer80;chTCHAR如定义了 _U
25、NICODE ,为 16 位字符或字符串,否则为8位字符 或字符串TCHAR chTmp;TCHARchName80;bBOOL布尔变量BOOLbE nabled;nint整形数int Len gth;nunsigen int或UINT无符号整形数UINTLen gth;wun sige n short或WORD16位无符号整形数WORD wPos;lLong或LONG32位整形数LONG lOffset;dwunsigen long或DWORD32位无符号整形数DWORD dwFileLe ngth;strstring或CString字符串变量stri ng strUserName;fflo
26、at浮点型变量float fStockPrice;dfdouble双精度浮点型变量double dfStockPrice;chwWCHAR16位字符或字符串WCHARchwKey;WCHAR chwBuffer80;shshort短整形数Short shMo nth;hrHRESULTAn OLE HRESULTHRESULT hr;vvoidA void. This is ofte n used with thep prefix to make pv, a poin ter toan unknown type.void * pvBuffer;p*指针CDocument* m pDoc;lpF
27、AR*远指针CDocument* lpDoc;lpszLPSTR32字符串指针LPSTRlpszFileName;lpszLPCSTR32-bitpoin terto con sta ntcharacter str ingLPCSTRlpszFileName;lpszLPCTSTR32-bit poin ter to con sta nt characterstr ingif UNICODE is definedLPCTSTRlpszFileName;hHANDLEHan dle to Win dows objectHANDLE hWnd;lpfn(*fn)()callbackFarpoin
28、tertoCALLBACK fun ctio nlpfnAbortWin dows对象名称缩写:C#语言编程规范Copyright 王:中兴信息技术有限公司第14页共 71 页Win dows对象例子变量VC MFC 类例子对象HWNDhWnd;CWnd*pWnd;HDLGhDlg;CDialog*pDlg;HDChDC;CDC*pDC;HGDIOBJhGdiObj;CGdiObject*pGdiObj;HPENhPe n;CPe n*pPe n;HBRUSHhBrush;CBrush*pBrush;HFONThFont;CFo nt*pFont;HBITMAPhBitmap;CBitmap*
29、pBitmap;HPALETTEhPalette;CPalette*pPalette;HRGNhRg n;CRg n*pRg n;HMENUhMe nu;CMe nu*pMe nu;HWNDhCtl;CStatic*pStatic;HWNDhCtl;CButto n*pBt n;HWNDhCtl;CEdit*pEdit;HWNDhCtl;CListBox*pListBox;HWNDhCtl;CComboBox*pComboBox;C#语言编程规范Copyright 王:中兴信息技术有限公司第15页共 71 页2.4 程序规则2.4.1 变量声明和定义2.4.1.1 注意要点当定义成员变量时,注
30、意用注释概要描述成员变量的使用。 不要定义本模块中不用的成员变量。尽量只定义私有成员变量不要定义不必要的变量,象下面这些情况(不是全部)定义一个FLAG,但FLAG只是当时被引用或者根本不引用。请直 接判定Boolean表达式.定义一个临时变量,它的作用是暂存一个函数的返回值,然后放到一 个表达式中计算表达式的值.如果可以的话,请直接返回表达式的值.定义从不引用的变量2.4.1.2 初始化定要初始化标志变量 定要初始化累计变量和循环的计数变量 定要初始化存储返回值的变量定要初始化数组的内容为0。2.4.2 数组、字符串2.421 注意要点字符串的长度不要过长,限制进程空间内自动变量占用的内存大
31、小。计算数组元素个数时注意使用strle n()函数。关键字符串数组的元素个数使用常量+1的方式定义。防止元素使用时越 界。2.4.2.2 初始化定要初始化数组的内容为0C+语言编程规范Copyright 王:中兴信息技术有限公司第16页共 71 页2.4.3 函数声明和定义243.1 注意要点函数一定要先声明后使用。函数原型话头文件中。函数没有参数的用void说明。尽量保持函数只有一个出口。不要写超过三层的嵌套逻辑(if,while,for;这样会牺牲程序的易读性,如果有这样的情况,需要拆分为多个函数。尽量简化main ()函数的逻辑尽量隐藏函数:区分公有函数、私有函数、保护函数、某个模块的
32、函数。对以上所有函数在适当位置进行声明。不要编写多种功能集于一身的函数,为了对参数更强的确认,请编写功能单一的函数。不同层次、不同功能的函数尽量放在不同的文件中。如果一个函数有返回值,则调用它的函数必须检验这个返回值。243.2 参数传递对内部数据类型参数,如函数内部不对其修改应使用值传递方式。对非内部数据类型参数应采用引用传递或指针传递方式尽量少用参数不确定的函数。在函数体的“入口处”,对参数的有效性进行检查。如果参数是指针,且仅作输入用,则应在类型前加con st,以防止该指针在函数体内被意外修改。例如:char *strcpy( char *strDestination, const c
33、har *strSource);如果输入参数以值传递的方式传递对象,则宜改用“const &”方式来传递,这样可以省去临时对象的构造和析构过程,从而提咼效率。例如:BOOL Fin dUser( co nst CStri ng & strUserName );参数不超过6个。尽量少写5、6个参数的函数。参数过多时可以考虑定义结构,把参数包含在其中。尽量保持函数的返回值为int型,而且保持返回0为成功。小于0表示错误。2.4.3.3 函数返回值显式定义函数返回值的类型,如果函数没有返回值,那么应声明为void类型。除了void返回值类型函数,函数都要有返回值。C+语言编程规范Co
34、pyright 王:中兴信息技术有限公司第17页共 71 页返回指针类型的函数用NULL表示失败。函数返回时尽量采用“返回引用”而不是“返回值”。例如:class Pers onpublic:Pers on(); Pers on();const stri ng& GetName() const retur n strName; string& GetAddress()co nst return strAddress; /不良用法private:stri ng strName;stri ng strAddress;避免这样的成员函数: 其返回值是指向成员的非const指针或引用,
35、如上面Person类中的GetAddress成员函数,因为这个操作可以改变strAddress的值,破坏了类 的封装性。千万不要返回局部变量或局部对象的引用,因为当函数返回时它就不存在了;也不要返回函数内部用new初始化的指针的引用,因为容易发生内存泄漏或异常。函数必须返回一个对象时不要试图返回一个引用。243.4 在函数中使用断言程序一般分为Debug版本和Release版本,Debug版本用于内部调试,Release版 本发行给用户使用。断言assert是仅在Debug版本起作用的宏,它用于检查“不应该”发生的情况。下 面示例是一个内存复制函数。在运行过程中,如果assert的参数为假,那
36、么程序就会中止(一般地还会出现提示对话,说明在什么地方引发了assert)。void *memcpy(void *pvTo, const void *pvFrom, size_t size)assert(pvTo != NULL) & (pvFrom != NULL);/使用断言assert (pbTo=pbFrom+size | pbFrom=pbTo+size);防止内存块重叠byte *pbTo = (byte *) pvTo;/防止改变pvTo的地址byte *pbFrom = (byte *) pvFrom; /防止改变pvFrom的地址while(size - 0 )*pb
37、To + = *pbFrom + ;return pvTo;示例 复制不重叠的内存块C+语言编程规范Copyright 王:中兴信息技术有限公司第18页共 71 页assert不是一个仓促拼凑起来的宏。为了不在程序的Debug版本和Release版本引起差别,assert不应该产生任何副作用。所以assert不是函数,而是宏。程序员可以把assert看成一个在任何系统状态下都可以安全使用的无害测试手段。如果程序在 assertassert处终止了,并不是说含有该 assertassert 的函数有错误,而是调用者出了差错,assertassert 可以帮助我们找到发生错误的原因。很少有比跟踪到
38、程序的断言,却不知道该断言的作用更让人沮丧的事了。你化了很多时间,不是为了排除错误,而只是为了弄清楚这个错误到底是什么。有的时候,程序 员偶尔还会设计出有错误的断言。所以如果搞不清楚断言检查的是什么,就很难判断错误是出现在程序中, 还是出现在断言中。 幸运的是这个问题很好解决,只要加上清晰的注释即可。这本是显而易见的事情, 可是很少有程序员这样做。这好比一个人在森林里,看到树上钉着一块 “危险”的大牌子。 但危险到底是什么?树要倒?有废井?有野兽? 除非告诉人们“危险”是什么,否则这个警告牌难以起到积极有效的作用。难以理解的 断言常常被程序员忽略,甚至被删除。断言不是用来检查错误的,使用断言捕
39、捉不应该发生的非法情况。不要混淆非法情况与错误情况之间的区别,后者是必然存在的并且是一定要作出处理的。在函数的入口处,使用断言检查参数的有效性(合法性),并且在程序员使用了无定义的特性时向程序员报警。函数定义得越严格,确认其参数就越容易。在编写函数时,要进行反复的考查,并且自问:“我打算做哪些假定? ”一旦确定了相应的假定,就要使用断言对所做的假定进行检验,或者重新编写代码去掉相应的假定。另外,还要问:“这个程序中最可能出错的是什么,怎样才能自动地查出 相应的错误? ”努力编写出能够尽早查出错误的测试程序。一般教科书都鼓励程序员们进行防错设计,但要记住这种编程风格可能会隐瞒错误。当进行防错设计
40、时,如果“不可能发生”的事情的确发生了,则要使用断言进行报警。C+语言编程规范Copyright 王:中兴信息技术有限公司第19页共 71 页2.4.4 语句244.1 嵌套限制禁止超过三层的嵌套。2.4.4.2 禁止语句一般的,尽是少用goto语句。用if语句来强调只执行两组语句中的一组。禁止else goto和elsereturn。2.5 排版格式规则良好的代码排版格式会使程序结构清晰,利于理解,方便查错。对于C+语言的排版格式可以遵循几种事实标准。以下提供一种排版格式的建议 最终目的要达到,开发出的代码具有美观、易读、风格统一的特点。2.5.1 源代码文件一个项目的源代码必须保证风格的一
41、致性,这不仅对于项目开发者、项 目集成者、管理者非常重要,而且利于代码的维护及再使用。分页清晰:源代码应保证每页少于60行;在明显的逻辑分界区要显式分页。2.5.2 空行空行起着分隔程序段落的作用。空行得体(不过多也不过少)将使程序的布局更加清晰。空行不会浪费内存,虽然打印含有空行的程序是会多消耗一些纸张,但是值得。 所以不要舍不得用空行。在每个类声明之后、每个函数定义结束之后都要加空行。参见示例2-3(a)在一个函数体内, 逻揖上密切相关的语句之间不加空行, 其它地方应加空行分隔。参见示例2-3(b)/空行/空行void Function1()while (con diti on)state
42、me nt1;/空行/空行if (con diti on)void Function2()stateme nt2;C+语言编程规范Copyright 王:中兴信息技术有限公司第20页共 71 页else/空行void Function3 ()stateme nt3;/空行stateme nt4;示例 2-3(a)函数之间的空行示例 2-3(b)函数内部的空行2.5.3 代码行一行代码只做一件事情,如只定义一个变量, 或只写一条语句。 这样的代码容易阅读,并且方便于写注释。if、for、while、do等语句自占一行,执行语句不得紧跟其后。不论执行语句有多 少都要加。这样可以防止书写失误。示例2
43、-4(a)为风格良好的代码行,示例2-4(b)为风格不良的代码行。C+语言编程规范Copyright 王:中兴信息技术有限公司第21页共 71 页int nWidth;/宽度int nHeight;/高度int nDepth;/深度int nWidth, nHeight, nDepth; /宽度高度深度x = a + b; y = c + d; z = e + f;X = a + b; y = c + d; z = e + f;if (nWidth nHeight) dosomething();if (nWidth =”、“=”、“ + + ”、“ * * ”、“ % % ”、“ &
44、”、“|”、“ ”这类操作符前后不加空格。对于表达式比较长的for语句和if语句,为了紧凑起见可以适当地去掉一些空格, 如for (i=0; i10;i+)和if (a=b) & (c= 2000)/良好的风格if(year=2000)/不良的风格if (a=b) & (c=b&c=d)/不良的风格for (i=0; i10; i+)/良好的风格for(i=0;i10;i+)/不良的风格for (i = 0; i 10; i +)/过多的空格x = a b ? a : b;/良好的风格x=a Fun cti on();/不要写成b - Function();示例 2-5
45、 代码行内的空格2.5.5 对齐程序的分界符和应独占一行并且位于同一列,同时与引用它们的语句左 对齐。 之内的代码块在右边数格处左对齐。示例2-4(a)为风格良好的对齐,示例2-4(b)为风格不良的对齐。void Function(int x)void Function(int x)/ program code/program codeif (condition)if (condition)/ program code/program codeelse else/ program code/program codefor (initialization; condition; update)f
46、or (initialization; condition; update)/ program code/program codeWhile (condition)/ program codewhile (condition)/ program codeC+语言编程规范Copyright 王:中兴信息技术有限公司第24页共 71 页如果岀现嵌套的,则使用缩进对齐,如:示例 2-6(a)风格良好的对齐示例 2-6(b)风格不良的对齐2.5.6 分行代码行最大长度宜控制在70至80个字符以内。代码行不要过长,否则眼睛看不过 来,也不便于打印。当表达式分为多行时,注意分行位置必须有逻辑意义尽量在操作
47、符,并且是低优先级的操作符时分行。操作符放在新行之首(以便突出操作符)拆分出的新行要进行适当的缩进,使排版整齐,语句可读。不要在单目运算处分行。if (very_lon ger_variable1 = veryon ger_variable12)& (very_lon ger_variable3 = very_lon ger_variable14)& (very_lon ger_variable5 = b & c d & c + f = g + h ; /复合表达式过于复杂不要有多用途的复合表达式。例如:d = (a = b + c) + r ;该表达式既求a值
48、又求d值。应该拆分为两个独立的语句:a = b + c;d = a + r;让表达式直观,避免在表达式中用赋值语句例如:if ( strle n(chBuffer)/不直观if ( strle n( chBuffer)!= 0 ) /直观if ( UserName.lsEmpty()/直观if ( !que ne.lsNotFull()/不直观if ( que ne.lsFull()/直观/表达式中用赋值语句不直观fArea = ( fWidth *= SCALE_FACTOR ) * ( fHeight *= SCALE_FACTOR );不要把程序中的复合表达式与“真正的数学表达式”混淆。
49、例如:读。C+语言编程规范Copyright 王:中兴信息技术有限公司第26页共 71 页if (a b c)/a b c是数学表达式而不是程序表达式并不表示if (ab) & (bc)而是成了令人费解的if ( (ab)=”或“=-EPSINON) & (x=EPSINON)其中EPSINON是允许的误差(即精度)。3.1.1.4 指针变量与零值比较应当将指针变量用“=”或“!=”与NULL比较。(记为NULL。尽管NULL的值与0相同,但是两者意义不3.1.1.5 补充说明程序中有时会遇到if/else/return if (con dition) return x;ret
50、urn y;改写为if (con diti on) return x;else return y;或者改写成更加简练的retur n (con diti on ? x : y);3.1.2 循环语句的效率C+/C循环语句中,for语句使用频率最高,while语句其次,do语句很少用。本节 重点论述循环体的效率。提高循环体效率的基本办法是降低循环体的复杂性。指针变量的零值是“空”同。假设指针变量的名字为if (p = NULL)if (p != NULL)不要写成if (p = 0)if (p != 0)或者if (p)if (!p)p,它与零值比较的标准if语句如下:/ p与NULL显式比较,
51、强调p是指针变量/容易让人误解p是整型变量/容易让人误解p是布尔变量的组合,应该将如下不良风格的程序C+语言编程规范Copyright:9中兴信息技术有限公司第35页共 71 页如果循环体内存在逻辑判断, 并且循环次数很大,宜将逻辑判断移到循环体的外面。 示例3-1(a)的程序比示例3-1(b)多执行了N-1次逻辑判断。并且由于前者老要进 行逻辑判断,打断了循环“流水线”作业,使得编译器不能对循环进行优化处理,降低了效率。如果N非常大,最好采用示例3-1(b)的写法,可以提高效率。如果N非常小,两者效率差别并不明显,采用示例3-1(a)的写法比较好,因为程序更加简洁。for (i=0; in;
52、 i+)if (con diti on)if (con diti on)for (i=0; in; i+)DoSomethi ng();DoSomethi ng();elseDoOtherthi ng();elsefor (i=0; in; i+)DoOtherthi ng();表3-1(a)效率低但程序简洁表3-1(b)效率高但程序不简洁3.1.3 for 语句的循环控制变量不可在for循环体内修改循环变量,防止for循环失去控制。建议for语句的循环控制变量的取值采用“半开半闭区间”写法。示例3-2(a)中的x值属于半开半闭区间“0 = x N”,起点到终点的间隔为N,循环次数为No示例3
53、-2(b)中的x值属于闭区间“0 = x = N-1”,起点到终点的间隔为N-1,循环次数为No相比之下,示例3-2(a)的写法更加直观,尽管两者的功能是相同的。for (in t i=0; in; i+)for (int i=0; i,引用使用操作 符.),但是它们似乎有相同的功能。指针与引用都是让你间接引用其他对象。它 们有什么区别呢?弓I用是被引用物的别名,对引用的任何操作就是对被引用物的操作。“引用传递” 的性质象“指针传递”,而书写方式象“值传递”。C+语言编程规范Copyright:9中兴信息技术有限公司第42页共 71 页引用被创建的同时必须被初始化(指针则可以在任何时候被初始化
54、)。要认识到在任何情况下都不能用指向空值的引用。一个引用必须总是指向某些对 象。因此如果你使用一个变量并让它指向一个对象,但是该变量在某些时候也可能不指向任何对象,这时你应该把变量声明为指针,因为这样你可以赋空值给该变量。相反, 如果变量肯定指向一个对象,例如你的设计不允许变量为空, 这时你就可以把变量声明 为引用。stri ng& rstr;/错误,引用必须被初始化stri ng strTmp(Test);string& rstr = strTmp;/正确,rstr指向strTmp指针没有这样的限制。string *pstrTmp; /未初始化的指针,合法但危险我们要避免让引
55、用指向空值。例如:char *pNull = 0;/设置指针为空值char& rRefer = *pNull; /让引用指向空值不存在指向空值的引用这个事实意味着使用引用的代码效率比使用指 针的要高。因为在使用引用之前不需要测试它的合法性。void Prin tDouble(c onst double& dfNumber)cout dfNumber;/不需要测试dfNumber,它肯定指向一个double值相反,指针则应该总是被测试,防止其为空:void prin tDouble(c onst double *pdfNumber)if (pdfNumber) /检查是否为NUL
56、L cout 只能重载为成员函数+= -= /= *= &= |= = %= = =建议重载为成员函数所有其它运算符建议重载为全局函数表3-2运算符的重载规则由于C+语言支持函数重载,才能将运算符当成函数来用,C语言就不行。对于运算符重载:(1)不要过分担心自己不会用,它的本质仍然是程序员们熟悉的函数。(2)不要过分热心地使用,如果它不能使代码变得更加易读易写,那就别用,否则会自找麻烦。不能被重载的运算符在C+运算符集合中,有一些运算符是不允许被重载的。这种限制是出于安全方面 的考虑,可防止错误和混乱。(1) 不能改变C+内部数据类型(如int,float等)的运算符。(2)不能重载.
57、,因为在类中对任何成员都有意义,已经成为标准用法。(3) 不能重载目前C+运算符集合中没有的符号,如#,$等。原因有两点,一是难以 理解,二是难以确定优先级。(4)对已经存在的运算符进行重载时,不能改变优先级规则,否则将引起混乱。3.4.2 函数参数的缺省值有一些参数的值在每次函数调用时都相同,书写这样的语句会使人厌烦。C+语言采用参数的缺省值使书写变得简洁(在编译时,缺省值由编译器自动插入)。C+语言编程规范Copyright:9中兴信息技术有限公司第47页共 71 页参数缺省值的使用规则:参数缺省值只能出现在函数的声明中,而不能出现在定义体中。例如:void Add( int m=0, i
58、 nt n=0); /正确,缺省值出现在函数的声明中void Add(i nt m=0, i nt n=0)/错误,缺省值出现在函数的定义体中如果函数有多个参数,参数只能从后向前挨个儿缺省,否则将导致函数调用语句怪 模怪样。正确的示例如下:void Function (i nt m, int n=0, int k=0);错误的示例如下:void Function (int m=0, int n, int k=0);要注意,使用参数的缺省值并没有赋予函数新的功能,仅仅是使书写变得简洁一些。它可能会提高函数的易用性, 但是也可能会降低函数的可理解性。所以我们只能适当地 使用参数的缺省值,要防止使用
59、不当产生负面效果。 示例3-3中,不合理地使用参数的 缺省值将导致重载函数output产生二义性。#in clude void Prin t( int m);void Print( int m, float a=0.0);void Print( int m)cout ” output int m endl ; void Print( int m, float a) cout output i nt m and float a (b) ? (a): (b)语句result = max(i, j) + 2 ;将被预处理器解释为result = (i) (j) ? (i) : (j) + 2 ;由于
60、运算符+比运算符:的优先级高,所以上述语句并不等价于期望的result = ( (i) (j) ? (i) : (j) ) + 2 ;如果把宏代码改写为#define max(a, b) ( (a) (b) ? (a): (b)则可以解决由优先级引起的错误。但是即使使用修改后的宏代码也不是万无一失的,例如语句result = max(i+, j);将被预处理器解释为result = (i+) (j) ? (i+) : (j);对于C+而言,使用宏代码还有另一种缺点:无法操作类的私有数据成员。让我们看看C+的“函数内联”是如何工作的。对于任何内联函数,编译器在符 号表里放入函数的声明(包括名字、参数类型、返回值类型)。如果编译器没有发现内联函数存在错误,那么该函数的代码也被放入符号表里。在调用一个内联函数时,编译器首先检查调用是否正确(进行类型安全检查
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 【正版授权】 ISO/IEC 30186:2025 EN Digital twin - Maturity model and guidance for a maturity assessment
- 【正版授权】 IEC 62007-2:2025 EN Semiconductor optoelectronic devices for fibre optic system applications - Part 2: Measuring methods
- 单位宪法宣传课件
- 卓越绩效管理课件教学
- 卒中患者体位管理课件
- 广州执信入学数学试卷
- 华为客户管理课件
- 海淀区中考数学试卷
- 衡阳小学6年级数学试卷
- 广益中学数学试卷
- 2025-2030成都市医疗机构行业市场发展分析及发展前景与投资研究报告
- 新版器械GCP培训课件
- 《小学生网络安全教育》课件
- 2025年高级评茶员技能鉴定理论考试题库浓缩500题-含答案
- 天翼云从业者题库练习测试题附答案
- 民丰县瑞安矿业投资有限公司民丰县卧龙岗年处理30万吨锑矿选厂及尾矿库建设项目报告书
- 山东济宁历年中考作文题(2004-2024)
- 心脏骤停后高质量目标温度管理专家共识2024
- 合同债权转让及违约金协议
- 售后服务电话回访管理办法
- 《中国糖尿病防治指南(2024版)》更新解读
评论
0/150
提交评论