下载
加入VIP
  • 专属下载特权
  • 现金文档折扣购买
  • VIP免费专区
  • 千万文档免费下载

上传资料

关闭

关闭

关闭

封号提示

内容

首页 VC++编程规范

VC++编程规范.doc

VC++编程规范

李飞彩
2017-09-19 0人阅读 举报 0 0 暂无简介

简介:本文档为《VC++编程规范doc》,可适用于综合领域

VC编程规范编写编程规范的目的(安全:增加代码的正确性和稳定性使它稳定可靠遵守编程规范可以大幅度减少各种易犯的错误和隐患。  (易读:保证代码的易读性和可维护性(美观:尽量统一项目组内人员的编程风格(便于代码调试和错误定位在编码时就注意留下跟踪的线索会使错误定位和修改更加容易。编程规范的作用范围只要能写出高质量的程序并不强求所有程序都必须完全遵循本编码规范。原则上:(外来的代码只要测试正确代码复查没有问题程序文档齐全可以有自己的规范和风格(过去的程序原则上不为了适合本规范而专门改写程序。但是如果方便也可以顺手做一些修改如加一些注释。(这个规范主要针对本开发组新开发的用VC编写的界面或业务逻辑模块的编写。某些模块如果有自己的编程风格请制订相应的文档加以说明。命名规则包括如下C要素的命名:类、结构、函数、变量、常量(包括资源、自定义消息)、宏、自定义类型等命名的主要原则是:(使用有意义的单词或多个词组合一目了然。不要使用人名、项目组名(命名时请考虑名字的唯一性不要使用容易引起混淆的名称。(长短要合适。多个词组合较长时,可以使用单词的缩写(主要采用Windows的命名风格对于类、函数和变量每个单词的首字符大写,其余小写常量和宏定义全部大写自己定义的类型(使用了typedef)全部大写指针使用LP大写前缀不要用MyFilecpp,testh,bitmapbmp,nByte,CClass等等没有意义的名字。临时使用的文件的名字要用函数生成避免使用“硬名字”如temp。不能使用程序员的姓名或缩写来命名如ylscpp。类的命名(以大写的C开头采用如下格式:CXXXYYYYY其中XXX指的是模块名称的缩写参见附录。YYYYY是类本身的名称例如:  CAdmDlgSearchID结构自定义类型(结构联合命名使用typedef后必须全部大写单词中间可以使用下划线连接。(如果不使用typedef则在全部大写的名字前加st。(结构变量的命名应尽量使用该结构的缩写前缀。前缀使用两个以上的小写字母。(自己定义的类型(使用了typedef)全部大写指针使用LP大写前缀函数(使用动宾词组表达函数实际所作的事(同名的函数(重载函数)在功能上应该完全相同,在参数上的差别也应一目了然(不得出现名字非常相近但功能不同的函数如CreatePage(),CreatePage()等变量变量命名原则上使用匈牙利命名法一般由“前缀+类型修饰+主体”等部分组成,如:gstrRegHome(前缀(以下划线分割)g:表示全局变量(包含全局静态变量)如:glpEnvt:表示线程的全局变量: 如:intdeclspec(thread)tnCountm:表示类成员变量(包含类静态变量)如:mdwFlagsgstr:表示全局的字符串常量 如:constTCHARgstrRegHome=T(“SoftwareFounderFounderAuthorTool”)(类型修饰(小写字母)参见附录。(主体使用一个或多个单词表示变量代表的确切含义,参见下面的大小写规则窗口菜单句柄等命名: hWndxxxx,hMenuxxxx常量(包括资源、自定义消息枚举,宏等)(宏定义和常量全要用大写(自定义的消息WMA(资源ID的命名:参见附录:资源ID的命名。(枚举类型:命名方式类似结构相应的前缀为enum。枚举值的命名一律大写(等同于宏)。枚举变量的命名按整数命名。(内部的限制量如列表的最大长度文件名的最大长度等统一使用MAXxxxxxxxxLEN来命名并集中放置在一个头文件中。数据库相关的限制值放在另一个头文件中定义。编程规则类(对自己定义的复杂类一定提供构造和析构函数(析构函数前一律加virtual防止因继承而产生的memoryleak。(有两种特殊情况:部支持位拷贝。某些特殊情况析构函数必须不是虚函数???)(在构造函数中初始化所有的成员变量在析构函数中删除可能申请的内存空间。(推荐采用公开的GetSet函数对成员变量进行存储而把成员变量设成protected或者private并加上注释。(声明成员函数和变量时要按功能分组给外部用的要排在前面(类的继承深度不要超过层(类的功能要单一公共函数个数一般要小于个(专门用于保存数据的类除外)内部protected函数以及private函数个数一般应小于个函数(长度一般禁止超过行(必须检查输入值是否合法(实现(成员)函数功能之前必须使用ASSERT()对输入参数的合法性进行检查尤其你定义的(成员)函数给别人调用时要判断其合法性。(函数返回值。函数有返回值的时候一般需要对返回值进行判断,除非有充分的理由确认一定能执行成功。根据返回值的结果决定后续的操作。特别指出的是:newCoCreateInstance一个对象之后一定要判断对象是否创建成功。如果不成功如何处理如果成功如何处理。(调用函数时要严格按照接口规范调用调用后要判断执行情况并做适当的错误处理(稍后会给出错误和异常处理规范)。(函数出口。为了程序跟踪调试方便所有函数请尽量保持最少的出口如果可能请保持一个出口。变量(初始化。当声明一个变量时编译器是不会自动将之清零的所以务必要自己初始化一下变量。(布尔变量统一使用BOOL(TRUE,FALSE)不要使用bool(true,false)在VC及之前版本sizeof(bool)=在VC及更高的版本  sizeof(bool)=,而在VC中BOOL定义为int型(一律用显式类型转换(float和BOOL禁止用"=="判断。BOOL应该用逻辑运算关系符而float应该用差值区间来判断“相等”。(在涉及永久存储和必须确保数据结构的长度不变的情况下一定要使用固定长度的数据类型比如int,int,int,int(类型的长度一律用sizeof()获得比如int的长度原来是bytes,现在是bytes,等IA出来后就会变成bytes常量  禁止直接引用常量而应该用通过#define和enum以及资源来引用。在程序中不要直接使用常量(如、“Error!”等)而要使用相应的枚举类型、常量定义和资源。具体来说对于只有相对意义的常量请使用枚举类型对于有绝对数值意义的常量请使用常量定义(如:#defineCPEPSILON)对于程序中要显示给最终用户看到的字符串常量请使用字符串资源(如:AfxMessageBox(“Error!”)请改为AfxMessageBox(IDSCPERRORMSG))。枚举和常量定义一般直接放在头文件中。对于字符串常量可以放在头文件中也可以放到资源文件中。前者的好处是便于移植(因为它跟Windows的资源没有关系)后者的好处是便于本地化(因为可以直接修改可执行文件的资源)请根据实际情况处理。在编写简易测试程序或者记录内部调试信息时可以直接使用字符串常量而不必去引用资源。指针(包括数组)(指针变量声明的书写风格:类型后面紧跟*号例如:DWORD* mpdw  建议采用DWORD *mpdw  不推荐DWORD*mpdw  不推荐(指针变量必须初始化。  对于类的成员变量可以在构造函数里初始化。对于函数内部局部变量声明时就请初始化。如DWORD*pdwFrame=(删除指针前请判定指针是否为。删除后把指针置为(即恢复初始状态)(严格防止越界对数组和缓冲区进行检查防止越界尤其是变长的情况下。你申请多少空间,就只能用多少。越界使用往往是造成程序无故突然退出的祸首也是各种安全漏洞的根源。禁止使用strcpy,sprintf等函数而要用strncpy,snprintf等函数替代。(同一指针new和delete时用的类型一定要完全一致 如:–  char*p=newcharint*p=(int*)p–  错误的删除方法:deletepwrong–  正确的删除方法:delete(char*)pright–  或者:deletepright 删数组用deletenew一个实例和多个实例时的delete方法不一样:–  newcharn和delete对应。–  newchar和delete对应。例如:–  char*p=newchardeletepright流程控制(除非特别必要一般不用goto宏和表达式(定义宏时参数使用扩号结果也应扩起来如: #defineSUB(a,b)((a)(b))这可确保如下形式的调用不会出错:*SUB(,)(如果有、||、!等逻辑运算符请把它们作用的表达式用"()"扩起来。字符串(尽量不要使用CString定义数据成员可以使用CString定义局部临时变量。原因:)由于CString的方法大都会Throw异常而使用过程中又每一步调用都检查是否发生异常又很不方便。这样容易导致异常发生而又非常难以定位错误)由于CString操作不停地申请、释放小块内存将导致系统效率降低(建议使用:TCHAR它屏蔽了字符类型(UnicodeANSI)。在这两种字符下TCHAR都工作正常。数据类型定义:TCHAR*,TCHAR用固定长度数组或者通过长度变量使用未知长度的数组。接口参数定义:使用BSTR它指向的是宽字节字符串)(BSTR:BasicSTRing)是结构化数据类型它前面的个Byte包含的是字符串的长度。const的使用(不需要修改类的成员变量的成员函数,将之声明为const,这样可以保证不出现不必要的修改。如:DWORDCBirthDay::GetBirthYear()const  {   returnmdwYear  }Get函数应该用const关键字修饰。(输入参数要有适当的用const修饰当不需要修改输入参数时应该将输入参数声明为const一种比较重要的情况是需要输入的参数是一个类的实例时请使用引用或者指针。严禁直接传送实例那样不仅效率低而且易出错不会带来任何好处。程序版式注释(在你劳神的地方请加上详细的注释说明。除了最简单的存取成员变量的SetGet成员函数之外其余大部分的函数写上注释是良好的习惯。尽量使你的程序让别人很容易看懂(太多的注释会使程序很难看但一些复杂的算法和数据结构处还是要加上注释的这样别人就容易看懂。否则时间长了你自己都未必看明白了  (推荐使用做注释每行不要超过字符(程序头要有说明(说明函数功能、参数定义、返回值和处理流程)鼓励尽量多的注释。(对于变量声明除了循环变量外一般都在行尾加注释重要变量要加详细注释。(头文件和cpp头部应有注释简单描述文件的内容(对于程序中的比较关键的算法和函数必须加注释{}的使用(放到行首需要匹配的上下对齐    推荐使用这种风格    if()    {          }    elseif()    {          }    不推荐这种风格:      if(){              }elseif(){              }    (即使只有一句也请使用括号。以便于将来扩充。(对于匹配的{},如果中间的代码行数较多或者{}嵌套层数较多请在}后面加上注释以便标识与哪个{匹配。空格、空行的使用(关键字后面一般要留有空格以便于阅读。(运算符前后一般留有空格以便于阅读。(相对独立的代码前后一般留有空行以便于阅读。(但空行、空格不能滥用。如连续多个空格、连续多个空行。(代码的长度每行不应超过字否则不利于阅读VC特有的问题DebugvsReleaseVC里最独有的问题就是Debug版本一切正常Release版本却运行却不正常甚至死机。除了VC的help里说的CommonProblemsSwitchingfromDebugtoReleaseBuild外其实最常见的病因如下:规范自定义消息响应函数的原型VC帮助中指出几种自定义消息响应函数的原型如下:ONMESSAGE(<message>,<memberFxn>)afxmsgLONGmemberFxn(UINT,LONG)ONREGISTEREDMESSAGE(<nMessageVariable>,<memberFxn>)afxmsgLONGmemberFxn(UINT,LONG)ONTHREADMESSAGE(<message>,<memberFxn>)afxmsgvoidmemberFxn(UINT,LONG)ONREGISTEREDTHREADMESSAGE(<nMessageVariable>,<memberFxn>)afxmsgvoidmemberFxn(UINT,LONG)程序中自定义消息的响应函数务必遵循上述规范否则将为害Release版本后果是严重的道路是曲折的!ASSERTTRACE可以使用ASSERT来提前发现你程序中潜在的错误if语句是说可能存在不同的情况而ASSERT语句是说肯定存在的情况如果ASSERT失败就说明在此之前已经发生了错误。TRACE则用于定位错误具体操作详见NFCTRACE(原NLETRACE)的相关说明。重要的函数(尤其是牵涉到内存分配或者较多指针操作的函数)进入时必须加入一句NFCTRACE()当有多个退出时则在每个退出口前加一句NFCTRACE()WarningLevel写程序时要把编译选项的“警告级别(WarningLevel)”置为最高级级最终编译结果不允许出现任何警告!任何警告都是错误可能的隐藏之地!用VC的DEBUGNEW防止memoryleakVC提供自己的检测memoryleak的方法只要你把这段代码加到cpp头部即可:#ifdefDEBUG#definenewDEBUGNEW#undefTHISFILEstaticcharTHISFILE=FILE#endif关于字符串、数字的重点标识为了便于查找、发现、并尽量避免直接使用字符串常量、数字常量请在各自的VC开发环境里对字符串、数字进行重点标识。方法如下:选择Tools>Option>Format,在Colors况中选择String、Number分别设定前景、背景色。建议:由于数字常量一般较短不必设置背景色。而对于字符串一般较长请设置背景色。工程文件工程文件必需完备、紧致不要在工程中包含没用的废弃文件也不能有空缺。调试和测试关键算法处一定要仔细进行静态检查并配上详细注释动态调试由于数据用例所限并不能解决所有潜在问题关键算法处必须进行仔细的静态代码检查务必使代码实现忠实于设计。单元测试的语句覆盖除去catch里的异常处理代码外要做到的语句覆盖测试时用VC带的profile来做语句覆盖检查。对于某些关键异常的处理要找特殊用例进行实际测试对于普通的异常处理稍后会给出的专门的异常处理编码规范。单元测试结束时必须提交相应的profile利用TRACE发现和调试错误●随时注意VC给出的TRACE信息●每次从DEBUG状态结束运行时查看TRACE信息●使用DEBUGNEW帮助查找memoryLeak●TRACE各种错误信息。一般的调试信息在放入Sourcesafe前请去掉以免影响别人。避免正常运行时的大量无意义的TRACE信息。使用断言(ASSERTVERIFY)●注意ASSERT与VERIFY的差别●区分不应该发生的情形(非法情形)与可能发生的情形(运行错误情形)●对意义不明确的断言加上注释●使用断言对函数参数进行确认查出对函数的非法调用●使用断言对函数的假定环境进行确认●使用断言检查不应该发生的情形●使用断言检查验证函数的正确性  调试代码不要产生副作用附录数据类型和一些MFC对象的缩写Char(term)    szTCHAR            sz,TCHAR*          psz,BSTR            bstrBSTR*            pbstrCStringclass    strInteger      nBoolean      bByte      bylong      lShort      sColorRef      clrUnsignedintegerUINT  uHandle      hWord      wDWORD      dwfloat      fDouble      dPointer      pFarPointer    pf,lpCharacter      cVoid      vComboBox          cmbListBox          lstButton          btnStaticText        txtGroupBox          grpCheckBox          chkRadioButton        btnCPoint,Point        ptRectangle          RECTCRectorRECT        rect(orxandycoordinatetypes)rcPositionType    posWindowHandle    hWnd附录:程序模块的划分和缩写各模块缩写:  Broadcast:    BroAdmin:      Adm……附录:资源ID的命名(一律用大写命名(资源对应文件的命名建议资源ID对应文件的命名采用和资源ID接近的命名方式。以便查找。如资源ID为: IDBBMPINFINITY,对应的资源文件为:bmpFounderInfinitybmp。前缀        资源类型      例IDRXX        Acceleratorormenu      IDRSYSMAINFRAMEIDDXX        Dialogbox          IDDSYSABOUTBOXIDCXX        Cursor            IDCSYSBLUECURIDIXX        Icon              IDISYSMAINICONIDBXX        Bitmap            IDBSYSBEGINIDSXX        String            IDSTTTITLEIDSERRxxxx    错误信息字符串      IDSERROPENFAILEDIDSMSGxxxx    提示信息字符串      IDSMSGPLAYLISTLOADIDPXX        Stringusedinmessagebox  IDPTTERRORMSG="xxxx"IDOK,IDCANCEL    StandardpushbuttonIDCaaaabbbb    Otherdialogcontrols    IDCPRCBUTTONDELIDMXX        Menuitem          IDMMMNEWIDXX        Command            IDMMNEWPROJECTIDWXX        Vieworchildwindows    IDWIOINPUTVIEW其中:XX标识某个模块的名字。IDCaaabbb:对话框中的Control,其中aaa表示对话框的缩写,bbb表示资源类型参见附录的缩写BTN:按钮CHK:checkBoxRAD:radioBoxEDIT:editCMB:ComboboxLIST:ListboxSTA:static(在需要时才命名,否则应定义为IDCSTATIC)SCR:ScrollbarSPIN:spinSLID:slidePROG:progressTREE:tree  TAB:tabREDIT:RichEditANI:Animation附录:文件头和函数头的注释版式文件头Copyright(c),北京北大方正电子有限公司Allrightsreserved文件名称:filenameh文件标识:????摘要:简要描述本文件的内容当前版本:作者:输入作者(或修改者)名字完成日期:年月日取代版本:原作者:输入原作者(或修改者)名字完成日期:年月日函数头Function:  系统初始化时调用该函数对内容模块进行初始化在CMainFrame创建后 由CBroadcastApp::InitInstance()调用Parameters:voidReturn:    TRUE  模块初始化成功  FALSE  模块初始化失败附录:建议.源文件应尽量使用格式。  这一点应该视情况而定  文件名只能包含字母、数字和下划线不得使用其他的字母。超长的文件名应使用缩写方式减少文件名的长度。建议使用如下的缩写的规则(部分情况可以有例外视具体情况而定):缩写一般可以去掉元音字母以及不发音字母单词的首字母一般应该保留。当一个单词必须缩成一个字母时应该选用最有代表性的字母或首字母。多音节的单词可以去掉后面的音节而只保留前面的第一、二音节。较短的二音节单词一般不缩写如果必须缩写可以只保留一个字母多个单词组成文件名时应该保留较重要的有意义的单词(或多留几个字母)其他单词可以使用简写或只用首字母去掉不必要的无意义的单词可以使用一些谐音表示一个单词如表示to表示for等等当单词数量少字母少的情况下不需要缩写较短的单词一般不缩写或缩写为一到二个字母避免整块拷贝代码段尽量避免整块复制代码段如果出现这样的情况要分析原因如果这段代码完成独立的功能应考虑使用函数否则应考虑使用宏定义。否则因为修改引起的不一致往往是错误的根源。尽量不要使用动态数组。可以使用CObArray但不要使用其动态增减特性。.文件命名cpp与h一一对应全局的宏如果不限在一个cpp中使用,可以单独定义头文件源文件命名应包含“前缀命名“下面列出前缀的含义●d:对话框以及派生类●b:基本的函数库或类库●i:Interface定义●m:媒体管理部分程序(除d,i以外)●其他文件一律以字母a开头(以便以后扩充)临时文件名必须调用系统函数生成,禁止使用固定文件名。一般情况下临时文件应在系统临时目录下(通过系统函数取到临时目录名)生成。关于包含文件:一般来说在*h文件里尽量不要#include"*h"。需要的话在*cpp文件里包含。可以通过声明类型(如:interfaceINle*classCNLe*等)等方式尽量避免。这样尽量降低文件间的依赖性!包含"*h"如果能明确路径的请务必使用完整路径!这样便于在其他机器上顺利编译运行。如:FdmNle工程下面FdmNlecpp里#include"AdminAdminh"#include"DBBrokerDBBrokerh"#include"DBBrokerDBBrokeric"头文件的书写规范头文件中尽量不要包含别的头文件头文件中应使用条件编译来保证该文件不被重复include(类尽量从CObject继承主要好处是以便使用CObList等collection类可以方便的serialize其次是可以使用RuntimeClass等高级特性。(禁止使用公有的成员变量(局部变量声明要求相应集中不要在函数内部随处声明变量。(功能要单一函数复杂度应小于。经验证明:当函数复杂度大于时其可能导致的BUG数也急剧增加。 TAB键TAB键统一定义为四个空格符源文件中不允许保留TAB键否则由于不同的开发环境以及编辑器在处理TAB键时不一致会导致代码显示混乱。 条件判断表达式的书写==,!=如果表达式有一边为常量如请把常量放到前面以避免把"=="写成"="。

用户评价(0)

关闭

新课改视野下建构高中语文教学实验成果报告(32KB)

抱歉,积分不足下载失败,请稍后再试!

提示

试读已结束,如需要继续阅读或者下载,敬请购买!

文档小程序码

使用微信“扫一扫”扫码寻找文档

1

打开微信

2

扫描小程序码

3

发布寻找信息

4

等待寻找结果

我知道了
评分:

/14

VC++编程规范

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利