以下为《c及c 规范》的无排版文字预览,完整格式请下载
下载前请仔细阅读文字预览以及下方图片预览。图片预览是什么样的,下载的文档就是什么样的。
高质量的工程,一般会做到:
代码简洁精炼,美观,可读性好,高效率,高某某,可移植性好,高某某,低耦合,没有冗余,不符合这些原则,必须特别说明。
规范性,代码有规可循。特殊排版、特殊语法、特殊指令,必须特别说明。
一、文件排版方面
1.包含头文件
1.1 先系统头文件,后用户头文件。
1.2 系统头文件,稳定的目录结构,应采用包含子路径方式。
1.3 自定义头文件,不稳定目录结构,应在dsp中指定包含路径。
1.4 系统头文件应用:#include
1.5 自定义同文件应用:#include "xxx.h"
1.6 只引用需要的头文件。
2.h和cpp文件
2.1 头文件命名为*.h,内联文件命名为*.inl;C++文件命名为*.cpp
2.2 文件名用大小写混合,或者小写混合。例如DiyMainview.cpp,infoview.cpp。不要用无意义的名称:例如XImage.cpp;SView.cpp;xlog.cpp;
2.3 头文件除了特殊情况,应使用#ifdef控制块。
2.4 头文件#endif应采用行尾注释。
2.5 头文件,首先是包含代码块,其次是宏定义代码块,然后是全局变量,全局常量,类型定义,类定义,内联部分。
2.6 CPP文件,包含指令,宏定义,全局变量,函数定义。
3.文件结构
3.1 文件应包含文件头注释和内容。
3.2 函数体类体之间原则上用2个空行,特殊情况下可用一个或者不需要空行。
4.空行
4.1 文件头、控制块,#include部分、宏定义部分、class部分、全局常量部分、全局变量部分、函数和函数之间,用两个空行。
二、注释方面
1.文件头注释
1.1 作者,文件名称,文件说明,生成日期(可选)
2.函数注释
2.1 关键函数必须写上注释,说明函数的用途。
2.2 特别函数参数,需要说明参数的目的,由谁负责释放等等。
2.3 除了特别情况,注释写在代码之前,不要放到代码行之后。
2.4 对每个#else或#endif给出行末注释。
2.5 关键代码注释,包括但不限于:赋值,函数调用,表达式,分支等等。
2.6 善未实现完整的代码,或者需要进一步优化的代码,应加上?// TODO ...
2.7 调试的代码,加上注释?// only for DEBUG
2.8 需要引起关注的代码,加上注释?// NOTE ...
2.9 对于较大的代码块结尾,如for,while,do等,可加上?// end for|while|do
三、命名方面
1.原则
1.1 同一性:在编写一个子模块或派生类的时候,要遵循其基类或整体模块的命名风格,保持命名风格在整个模块中的同一性。
1.2 标识符组成:标识符采用英文单词或其组合,应当直观且可以拼读,可望文某某,用词应当准确,避免用拼音命名。
1.3 最小化长度 && 最大化信息量原则:在保持一个标识符意XX确的同时,应当尽量缩短其长度。
1.4 避免过于相似:不要出现仅靠大小写区分的相似的标识符,例如"i"与"I","function"与"Function"等等。
1.5 避免在不同级别的作用域中重名:程序中不要出现名字完全相同的局部变量和全局变量,尽管两者的作用域不同而不会发生语法错误,但容易使人误解。
1.6 正确命名具有互斥意义的标识符:用正确的反义词组命名具有互斥意义的标识符,如:"nMinValue"?和?"nMaxValue","GetName()"?和"SetName()"?….
1.7 避免名字中出现数字编号:尽量避免名字中出现数字编号,如Value1,Value2等,除非逻辑上的确需要编号。这是为了防止程序员偷懒,不肯为命名动脑筋而导致产生无意义的名字(因为用数字编号最省事)。
2.T,C,M,R类
2.1 T类表示简单数据类型,不对资源拥有控制权,在析构过程中没有释放资源动作。
2.2 C表示从CBase继承的类。该类不能从栈上定义变量,只能从堆上创建。
2.3 M表示接口类。
2.4 R是资源类,通常是系统固有类型。除了特殊情况,不应在开发代码中出现R类型。
3.函数名
3.1 M类的函数名称应采用HandleXXX命名,例如:HandleTimerEvent;不推荐采用java风格,例如?handleTimerEvent;除了标准c风格代码,不推荐用下划线,例如,handle_event。
3.2 Leave函数,用后缀L。
3.3 Leave函数, 内容过长,仅展示头部和尾部部分文字预览,全文请查看图片预览。 型成员。
用enum取代(一组相关的)常量。
不要使用魔鬼数字。
尽量用引用取代指针。
定义变量完成后立即初始化,勿等到使用时才进行。
如果有更优雅的解决方案,不要使用强制类型转换。
六、表达式
避免在表达式中用赋值语句。
避免对浮点类型做等于或不等于判断。
不能将枚举类型进行运算后再赋给枚举变量。
在循环过程中不要修改循环计数器。
检测空指针,用?if( p )
检测非空指针,用?if( ! p )
七、函数
1.引用
1.1 引用类型作为返回值:函数必须返回一个存在的对象。
1.2 引用类型作为参数:调用者必须传递一个存在的对象。
2.常量成员函数
2.1 表示该函数只读取对象的内容,不会对对象进行修改。
3.返回值
3.1 除开void函数,构造函数,析构函数,其它函数必须要有返回值。
3.2 当函数返回引用或指针时,用文字描述其有效期。
4.内联函数
4.1 内联函数应将函数体放到类体外。
4.2 只有简单的函数才有必要设计为内联函数,复杂业务逻辑的函数不要这么做。
4.3 虚函数不要设计为内联函数。
5.函数参数
5.1 只读取该参数的内容,不对其内容做修改,用常量引用。
5.2 修改参数内容,或需要通过参数返回,用非常量应用。
5.3 简单数据类型用传值方式。
5.4 复杂数据类型用引用或指针方式。
八、类
1.构造函数
1.1 构造函数的初始化列表,应和类的顺序一致。
1.2 初始化列表中的每个项,应独占一行。
1.3 避免出现用一个成员初始化另一个成员。
1.4 构造函数应初始化所有成员,尤其是指针。
1.5 不要在构造函数和析构函数中抛出异常。
2.纯虚函数
2.1 M类的虚函数应设计为纯虚函数。
3.构造和析构函数
3.1 如果类可以继承,则应将类析构函数设计为虚函数。
3.2 如果类不允许继承,则应将类析构函数设计为非虚函数。
3.3 如果类不能被复制,则应将拷贝构造函数和赋值运算符设计为私有的。
3.4 如果为类设计了构造函数,则应有析构函数。
4.成员变量
4.1 尽量避免使用mutable和Volatile。
4.2 尽量避免使用公有成员变量。
5.成员函数
5.1 努力使类的接口少而完备。
5.2 尽量使用常成员函数代替非常成员函数,const函数
5.3 除非特别理由,绝不要重新定义(继承来的)非虚函数。(这样是覆盖,基类的某些属性无初始化)
6.继承
6.1 继承必须满足IS-A的关系,HAS-A应采用包含。
6.2 虚函数不要采用默认参数。
6.3 除非特别需要,应避免设计大而全的虚函数,虚函数功能要单一。
6.4 除非特别需要,避免将基类强制转换成派生类。
7.友元
7.1 尽量避免使用友元函数和友元类。
九、错误处理
申请内存用new操作符。
释放内存用delete操作符。
new和delete,new[]和delete[]成对使用。
申请内存完成之后,要检测指针是否申请成功,处理申请失败的情况。
谁申请谁释放。优先级:函数层面,类层面,模块层面。
释放内存完成后将指针赋空,避免出现野指针。
使用指针前进行判断合法性,应考虑到为空的情况的处理。
使用数组时,应先判断索引的有效性,处理无效的索引的情况。
代码不能出现编译警告。
使用错误传递的错误处理思想。
卫句风格:先处理所有可能发生错误的情况,再处理正常情况。
嵌套do-while(0)宏:目的是将一组语句变成一个语句,避免被其他if等中断。
十、性能
使用前向声明代替#include指令。Class M;
尽量用++i代替i++。即用前缀代替后缀运算。
尽量在for循环之前,先写计算估值表达式。
尽量避免在循环体内部定义对象。
避免对象拷贝,尤其是代价很高的对象拷贝。
避免生成临时对象,尤其是大的临时对象。
注意大尺寸对象数组。
80-20原则。
十一、兼容性
遵守ANSI C和ISO C++国际标准。
确保类型转换不会丢失信息。
注意双字节字符的兼容性。
注意运算溢出问题。
不要假设类型的存储尺寸。
不要假设表达式的运算顺序。
不要假设函数参数的计算顺序。
不要假设不同源文件中静态或全局变量的初始化顺序。
不要依赖编译器基于实现、未明确或未定义的功能。
将所有#include的文件名视为大小写敏感。
避免使用全局变量、静态变量、函数静态变量、类静态变量。在使用静态库,动态库,多线程环境时,会导致兼容性问题。
不要重新实现标准库函数,如STL已经存在的。
[文章尾部最后300字内容到此结束,中间部分内容请查看底下的图片预览]请点击下方选择您需要的文档下载。
以上为《c及c 规范》的无排版文字预览,完整格式请下载
下载前请仔细阅读上面文字预览以及下方图片预览。图片预览是什么样的,下载的文档就是什么样的。