编程规范(2016年1月11号)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编程规范(2016年1月11号)相关的知识,希望对你有一定的参考价值。
一、文件结构
1.1版权和版权的声明
(1)版权信息。
(2)文件名称,标识符,摘要。
(3)当前版本号,作者/修改者,完成日期。
(4)版本历史信息
1.2头文件的结构
(1)头文件开头处的版权和版权声明。
(2)预处理块。
a.为了防止头文件被重复引用,应当用ifndef/define/endif结构产生预处理块。
b.用#include<xx.h>格式来引用标准的头文件(编译器将从标准库目录开始搜索)。
c.用#include"xx.h"格式来引用非标准的头文件(编译器将从用户的工作目录开始搜索)。
(3)函数和类结构声明等。
a.头文件中只存放“声明”而不存放“定义”
b.不提倡使用全局变量,尽量不要在头文件中出现像externa into value 这类声明
1.3定义文件的结构
(1)定义文件开头处的版权和版本声明。
(2)对一些头文件的引用。
(3)程序的实现体(包括数据和代码)。
1.4头文件的作用
(1)通过头文件来调用库功能。
(2)头文件能加强类型安全检查。
1.5目录结构
通常将头文件和定义文件分别保存于不同的目录,以便于维护。尽可能将相关的东西放在一块。
INCLUDE 目录放对外提供服务的API 函数定义,数据结构的定义。
SRC目录放原程序。
DOC放说明文档。
TEST目录放使用和测试的例子
中间定义的INLUDE文件可以放在SRC中,如果SRC分成了多个子目录,也可以放在一子目录下
二、程式的版本
2.1空行
a.在每个类声明之后、每个函数定义结束之后都要加空行,其他地方应加空行分隔。
b.在一个函数体内,逻辑上密切相关的语句之间不加空行,其他地方应加空行分隔。
2.2代码行
a.一行代码只做一件事情,如只定义一个变量,或只写一条语句。代码容易阅读,方便注释。
b.if、for、while、do等语句只占一行,执行语句不得紧跟其后。
建议:尽可能在定义变量的同时初始化该变量(就近原则)
2.3代码行内的空格
a.关键字之后要留空格。
b.函数名之后不要留空格,紧跟左括号,以与关键字区别。
c.‘(’向后紧跟,‘)’、‘,’、‘;’向前紧跟,紧跟处不留空格。
d.‘,’之后要留空格,如Function(x,y,z)。如果‘;’不是一行的结束符号,其后要留空格。
e.赋值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符等二元操作符的前后应当加空格。
f.一元操作符等前后不加空格。
g.像“[]”、“.”、“->”这类操作符前后不加空格。
h.对于表达式比较长的for语句和if语句,为了紧凑起见可以适当地去掉一些空格。
上面的建议并不绝对。
2.4对齐
a.程序的分界符‘{’和‘}’应独占一行并且位于同一列,同时与引用它们的语句左对齐。
b.{}之内的代码块在‘{’右边数格处左对齐。
2.5长行拆分
a.代码行最大长度宜控制在70至80个字符以内。
b.长表达式要在低优先级操作符处拆分成新行,操作符放在新行之首。
2.6修饰符的位置
a.应当将修饰符*和&紧靠变量名
2.7注释
a.注释是对代码的“提示”,而不是文档。
b.如果代码本来就是清楚的,则不必加注释。
c.边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。
d.注释应当准确、易懂,防止注释有二义性。
e.尽量避免在注释中使用缩写,特别是不常用缩写。
f.注释的位置应与被描述的代码相邻。
g.当代码比较长吗,特别是有多重嵌套时,应当在一些段落的结束处加注释。
2.8类的版式
两种:
(1)将private类型的数据写在前面,而将public类型的函数写在后面
a.采用这种版式的程序员主张类的设计“以数据为中心”,重点关注类的内部结构。
(2)将public类型的函数写在前面,而将private类型的数据写在后面
b.采用这种版式的程序员主张类的设计“以行为为中心”,重点关注类应该提供什么样的接口。
三、命名规则
3.1共性规则
a.标识符应当直观且可以拼读,可望文知意,不必进行“解码”。
b.标识符的长度应当符合“min-length && max-information”原则。
c.命名规则尽量与所采用的操作系统或开发工具的风格保持一致。
d.程序中不要出现仅靠大小写区分的相似的标识符。
e.不要出现标识符完全相同的局部变量和全局变量,尽管两者的作用域不同而不会发生语法错误,但会使人误解。
f.变量的名字应当使用“名词”或者“形容词+名词”。
g.全局函数的名字应当使用“动词”或者“动词+名词”(动宾词组)。
类的成员函数应当只使用“动词”,被省略掉的名词就是对象本身。
h.用正确的反义词组命名具有互斥意义的变量或相反动作的函数等
i.尽量避免名字中出现数字编号,如Value1,Value2等,除非逻辑上的确需要编号。
3.2简单的Windows应用程序命名规则
a.类名和函数名用大写字母开头的单词组合而成。
b.变量和参数用小写字母开头的单词组合而成。
c.常用全用大写的字母,用下划线分割单词。
d.静态变量加前缀s_(表示static)。
e.如果不得已需要全局变量,则使全局变量加前缀g_(表示global)。
f.类的数据成员加前缀m_(表示member),这样可以避免数据成员与成员函数的参数同名。
g.为了防止某一软件库中的一些标识符和其他软件库中的冲突,可以为各种标识符加上能反映软件性质的前缀。
四、表达式和基本语句
4.1运算符的优先级
a.如果代码行中的运算符比较多,用括号确定表达式的操作顺序,避免使用默认的优先级。
4.2复合表达式
a.不要编写太复杂的复合表达式。
b.不要有多用途的复合表达式。
c.不要把程序中的复合表达式与“真正的数学表达式”混淆。
4.3if语句
4.3.1布尔变量与零值比较
a.不可以将布尔变量直接与TRUE、FALSE或者1、0进行比较。
4.3.2整型变量与零值比较
a.应当将整型变量用“==”或“!=”直接与0比较。
4.3.3浮点变量与零值比较
a.不可将浮点变量用“==”或“!=”与任何数字比较。
4.3.4指针变量与零值比较
a.应当将指针变量用“==”或“!=”与NULL比较。
4.4 循环语句的效率
for语句使用频率最高,while语句其次,do语句很少用。提高循环效率的基本方法是降低循环体的复杂性。
a.在多重循环中,如果有可能,应当将最长的循环放在最内层,最短的循环放在最外层,以减少CPU跨切循如果循环体内存在环层数的次数
b.如果循环体内存在逻辑判断,并且循环次数很大,宜将逻辑判断移动到循环体的外面。
4.5for 语句的循环控制变量
a.不可在for循环体内修改循环变量,防止for循环失去控制。
b.建议for语句的循环控制变量的取值采用“半开半闭区间”写法
4.6switch语句
a.每个case语句的结尾不要忘了加break,否则将导致多个分支重叠(除非有意使多个分支重叠)。
b.不要忘记最后那个default分支。default:break;
4.7goto语句
意外处理可以用向后的goto,但要安排合适的处理点,一般先定义处理点,再做GOTO。
五、常量
5.1为什么需要常量
a.尽量使用含义直观的常量来表示那些将在程序中多次出现的数字或字符串。
5.2const与#define的比较
a.在C++程序中只使用const常量而不使用宏常量,即:const常量完全取代宏常量。
5.3常量定义规则
a.需要对外公开的常量放在头文件中,不需要对外公开的常量在定义文件的头部。
为了便于管理,可以把不同模块的常量集中放在一个公共的头文件中。
b.如果某一常量与其他常量密切相关,应在定义中包含这种关系,而不应给出一些孤立的值。
5.4类中的常量
不能在类声明中初始化const数据成员。const数据成员的初始化只能在类构造函数的初始化表中进行。
怎样才能建立在整个类中都恒定的常量呢?
答:别指望const数据成员了,应该用类中的枚举常量来实现。
enum{a=100,b=200}; 枚举常量不会占用对象的存储空间,在编译时被全部求值。
枚举常量的缺点是:踏的隐含数据类型是整数,其最大值有限,且不能表示浮点数。
六、函数设计
6.1参数的规则
a.参数的书写要完整,不要贪图省事只写参数的类型而省略参数名字。如果函数没有参数,则用void填充。
b.参数名要恰当,顺序要合理。
c.如果参数是指针,且仅作输入用,则应在类型前加const,以防止该指针在函数体内被意外修改。
d.如果输入参数以值传递的方式传递对象,则宜改用“const &”方式来传递,这样可以省去临时对象的构造和析构过程,从而提高效率。
e.避免函数有太多的参数,参数个数尽量控制在5个以内。
f.尽量不要使用类型和数目不确定的参数。
6.2返回值得规则
a.不要省略返回值的类型。
b.函数名字与返回值类型在语义上不可冲突。如:getchar()不是char类型而是int类型。
c.不要将正常值和错误标志混在一起返回。正常值用输出参数获得,而错误标志用return语句返回。
d.有时候函数原本不需要返回值,但为了增加灵活性如支持链式表达,可以附加返回值。
e.如果函数的返回值是一个对象,有些场合用“引用传递”替换“值传递”可以提高效率。
而有些场合只能用“值传递”而不能用“引用传递”,否则会出错。
6.3函数内部实现的规则
a.在函数体的“入口处”,对参数的有效性进行检查。
b.在函数体的“出口处”,对return语句的正确性和效率进行检查。
6.4其他建议
a.函数的功能要单一,不要设计多用途的函数。
b.函数的规模要小,尽量控制在50行代码之内。
c.尽量避免函数带有“记忆”功能。相同的输入应当产生相同的输出。建议少用static局部变量。
d.不仅要检查输入参数的有效性,还要检查通过其他途径进入函数体内的变量的有效性,例如全局变量、文件句柄等。
e.用于出错处理的返回值一定要清楚,让读者不容易忽视或误解情况。
6.5使用断言
如果程序在assert处终止了,并不是说含有该assert的函数有错误,而是调用者出了差错,assert可以帮助我们找到发生错误的原因。
6.6引用与指针的比较
a.引用被创建的同时必须被初始化(指针可以在任何时候被初始化)。
b.不能有NULL引用,引用必须与合法的存储单元关联(指针则可以是NULL)。
c.一旦引用被初始化,就不能改变引用的关系(指针则可以随时改变所指的对象)。
七、内存管理
7.1内存分配方式
a.从静态存储区域分配。
b.在栈上创建。
c.从堆上分配,也称动态内存分配。
7.2常见的内存错误及其对策
常见错误:
a.内存分配未成功,却使用了它。
b.内存分配虽然成功,但是未初始化就引用它。
c.内存分配成功并且已经初始化,但操作越过了内存的边界。
d.忘记了释放内存,造成内存泄露。
e.释放了内存却继续使用它。
对策:
a.用malloc或new申请内存之后,应该立即检查指针值是否为NULL。防止使用指针值为NULL的内存。
b.不要忘记为数组和动态内存符初值。防止将为被初始化的内存作为右值使用。
c.避免数组或指针的下标越界,特别要当心发生“多1”或者“少1”操作。
d.动态内存的申请与释放必须配对,防止内存泄漏。
e.用free或delete释放了内存之后,立即将指针设置为NULL,防止产生“野指针”。
7.3指针与数组的对比
7.3.1修改内容
常量字符串的内容是不可以被修改的。
7.3.2内容复制与比较
不能对数组进行直接复制与比较。
7.3.3计算机内存容量
注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。
7.4指针参数是如何传递内存的
如果函数的参数是一个指针,不要指望用该指针去申请动态内存。
7.5free和delete
它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。
7.6动态内存会被自动释放吗
函数体内的局部变量在函数结束时自动消亡。
(1)指针消亡了,并不代表它在所指的内存会被自动释放。
(2)内存被释放了,并不代表指针会消亡或者成了NULL指针。
7.7杜绝“野指针”
“野指针”不是NULL指针,是指向“垃圾”内存的指针。
“野指针”的成因主要有两种:
a.指针变量没有被初始化。
b.指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。
c.指针操作超越了变量的作用范围。
7.8有了malloc/free为什么还要new/delete
malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。
malloc与free中不包含构造和析构函数。
7.9内存耗尽怎么办
如果在申请内存时找不到足够大的内存块,malloc和new将返回NULL指针,宣告内存申请失败。
三种方式来处理:
a.判断指针是否为NULL,如果是则马上用return语句终止本函数。
b.判断指针是否为NULL,如果是则马上用exit(1)终止整个程序的运行。
c.为new和malloc设置异常处理函数。
7.10 一些心得体会
a.越是怕指针,就越要使用指针。不会正确使用指针,肯定算不上合格的程序员。
b.必须养成“使用调试器逐步跟踪程序”的习惯,只有这样才能发现问题的本质。
八、C++函数的高级特性
8.1重载、覆盖、隐藏
重载的特征:
a.相同的范围(在同一个类中);
b.函数名字相同;
c.参数不同;
d.virtual关键字可有可无。
覆盖是指派生类函数覆盖基类函数,特征:
a.不同的范围(分别位于派生类与基类);
b.函数名字相同;
c.参数相同;
d.基类函数必须有virtual关键字。
隐藏规则:
隐藏是指派生类的函数屏蔽了与其同名的基类函数
a.如果派生类的函数与基类的函数同名,但参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别被重载混淆)。
b.如果派生类的函数与基类的函数同名,并且参数也相同。但是基类函数没有virtual关键字。此时,基类的函数将被隐藏(注意别被覆盖混淆)。
十一、效率问题
不要一味地追求程序的效率,应当在满足正确性、可靠性、健壮性、可读性等质量因素的前提下,设法提高程序的效率。
以提高程序的全局效率为主,提高局部效率为辅。
在优化程序的效率时,应当先找出限制效率的“瓶颈”,不要在无关紧要之处优化。
先优化数据结构和算法,再优化执行代码。
不要最求紧凑的代码,因为紧凑的代码并不能产生高效的机器码。
以上是关于编程规范(2016年1月11号)的主要内容,如果未能解决你的问题,请参考以下文章