c\c++编程规范

c\c++编程规范

一、文件结构    

1.1 版权和版本的声明
版权和版本的声明位于头文件和定义文件的开头(参见示例1-1),主要内容有:
(1)版权信息。
(2)文件名称,标识符,摘要。
(3)当前版本号,作者/修改者,完成日期。
(4)版本历史信息。

/* 
* 版权信息
* All rights reserved. 
* 
* 文件名称:filename.h 
* 文件标识:
* 摘  要:简要描述本文件的内容
* 
* 当前版本:1.1
* 作  者:输入作者(或修改者)名字
* 完成日期:xxxx年xx月xx日
* 
* 取代版本:1.0 
* 原作者  :输入原作者(或修改者)名字
* 完成日期:xxxx年xx月xx日
*
*/ 
1.2 头文件的结构
为了防止头文件被重复引用,应当用ifndef/define/endif结构产生预处理块。

用#include <filename.h> 格式来引用标准库的头文件(编译器将从标准库目录开始搜索);
用#include “filename.h” 格式来引用非标准库的头文件(编译器将从用户的工作目录开始搜索)。

头文件中只存放“声明”而不存放“定义”
不提倡使用全局变量,尽量不要在头文件中出现象extern int value 这类声明。

#ifndef GRAPHICS_H // 防止graphics.h被重复引用
#define GRAPHICS_H 
#include <math.h>   // 引用标准库的头文件
… 
#include “myheader.h”   // 引用非标准库的头文件
… 
void Function1(…);  // 全局函数声明
… 
class Box    // 类结构声明
{ 
… 
}; 
#endif 
1.3 定义文件的结构

假设定义文件的名称为graphics.cpp,定义文件的结构参见示例:

#include “graphics.h”  // 引用头文件
… 
// 全局函数的实现体
void Function1(…) 
{ 
… 
} 
// 类成员函数的实现体
void Box::Draw(…) 
{ 
… 
}
1.4 头文件的作用

(1)通过头文件来调用库功能。

(2)头文件能加强类型安全检查。

二、程序的排版

2.1 空行

在每个类声明之后、每个函数定义结束之后都要加空行。

在一个函数体内,逻揖上密切相关的语句之间不加空行,其它地方应加空行分隔。


2.2 代码行

1.一行代码只做一件事情,如只定义一个变量,或只写一条语句。这样的代码容易阅读,并且方便于写注释。

if、for、while、do等语句自占一行,执行语句不得紧跟其后。不论执行语句有多少都要加{}。这样可以防止书写失误。

2.尽可能在定义变量的同时初始化该变量(就近原则)。如果变量的引用处和其定义处相隔比较远,变量的初始化很容易被忘记。如果引用了未被初始化的变量,可能会导致程序错误。


2.3 代码行内的空格

1.关键字之后要留空格。象if、for、while等关键字之后应留一个空格再跟左括号‘(’,以突出关键字。

函数名之后不要留空格,紧跟左括号‘(’,以与关键字区别。

2.‘(’向后紧跟,‘)’、‘,’、‘;’向前紧跟,紧跟处不留空格。‘,’之后要留空格,如Function(x, y, z)。如果‘;’不是一行的结束符号,其后要留空格,如for (initialization; condition; update)。

3.赋值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符,如“=”、“+=” 、“>=”、“<=”、“+”、“*”、“%”、“&&”、“||”、“<<”,“^”等二元操作符的前后应当加空格。

4.一元操作符如“!”、“~”、“++”、“--”、“&”(地址运算符)等前后不加空格。象“[]”、“.”、“->”这类操作符前后不加空格。

5.对于表达式比较长的for语句和if语句,为了紧凑起见可以适当地去掉一些空格,如for (i=0; i<10; i++)和if((a<=b) && (c<=d)) 

void Func1(int x, int y, int z); // 良好的风格
void Func1 (int x,int y,int z); // 不良的风格
if (year >= 2000) // 良好的风格
if(year>=2000) // 不良的风格
if ((a>=b) && (c<=d)) // 良好的风格
if(a>=b&&c<=d) // 不良的风格
for (i=0; i<10; i++) // 良好的风格
for(i=0;i<10;i++) // 不良的风格
for (i = 0; I < 10; i ++) // 过多的空格
x = a < b ? a : b; // 良好的风格
x=a<b?a:b; // 不好的风格
int *x = &y; // 良好的风格
int * x = & y; // 不良的风格
array[5] = 0; // 不要写成 array [ 5 ] = 0; 
a.Function(); // 不要写成 a . Function(); 
b->Function(); // 不要写成 b -> Function(); 
2.4 对齐

程序的分界符‘{’和‘}’应独占一行并且位于同一列,同时与引用它们的语句左对齐。

{ }之内的代码块在‘{’右边数格处左对齐。


2.5 长行拆分

1.代码行最大长度宜控制在70至80个字符以内。

2.长表达式要在低优先级操作符处拆分成新行,操作符放在新行之首(以便突出操作符)。拆分出的新行要进行适当的缩进,使排版整齐,语句可读。


2.6 修饰符的位置

1.应当将修饰符* 和  &  紧靠变量名
例如:
char  *name; 
 int  *x, y;  // 此处y不会被误解为指针

2.7 注释

1.注释的位置应与被描述的代码相邻,可以放在代码的上方或右方,不可放在下方。

2.当代码比较长,特别是有多重嵌套时,应当在一些段落的结束处加注释,便于阅读。


2.8 类的版式


三、命名规则

3.1 共性规则

1.命名规则尽量与所采用的操作系统或开发工具的风格保持一致。

2.程序中不要出现标识符完全相同的局部变量和全局变量,尽管两者的作用域不同而不会发生语法错误,但会使人误解。

3.尽量避免名字中出现数字编号,如Valu e1 ,Va lu e2等,除非逻辑上的确需要编号。

3.2 简单的Windows应用程序命名规则

1.类名和函数名用大写字母开头的单词组合而成。
例如:

class Node; // 类名
class LeafNode; // 类名
 void Draw(void);    // 函数名
 void SetValue(int value); // 函数名

2.变量和参数用小写字母开头的单词组合而成。
例如:

BOOL flag; 
 int drawMode; 

3.常量全用大写的字母,用下划线分割单词。
例如:

 const int MAX = 100; 
 const int MAX_LENGTH = 100; 

4.静态变量加前缀s_(表示static)。

5.如果不得已需要全局变量,则使全局变量加前缀g_(表示global)。

6.类的数据成员加前缀m_(表示member),这样可以避免数据成员与成员函数的参数同名。

四、表达式和基本语句

1.不可将布尔变量直接与TRUE、FALSE或者1、0进行比较。

假设布尔变量名字为flag,它与零值比较的标准if语句如下:

if (flag)  // 表示flag为真
if (!flag) // 表示flag为假
其它的用法都属于不良风格,例如:
 if (flag == TRUE) 
 if (flag == 1 )  
 if (flag == FALSE)   
 if (flag == 0)  
2.整型变量与零值比较应当将整型变量用“==”或“!=”直接与0比较。
假设整型变量的名字为value,它与零值比较的标准if语句如下:

if (value == 0)   
if (value != 0) 
不可模仿布尔变量的风格而写成
if (value)   // 会让人误解value是布尔变量
if (!value)  
3.浮点变量与零值比较。不可将浮点变量用“==”或“!=”与任何数字比较。千万要留意,无论是float还是double类型的变量,都有精度限制。  所以一定要避免将浮点变量用“==”或“!=”与数字比较,应该设法转化成“>=”或“<=”形式。
假设浮点变量的名字为x,应当将
if (x == 0.0)  // 隐含错误的比较
转化为
#define EPSINON 0.00001
if ((x>=-EPSINON) && (x<=EPSINON)) 
其中EPSINON是允许的误差(即精度)。
5.循环语句的效率

在多重循环中,如果有可能,应当将最长的循环放在最内层,最短的循环放在最外层,以减少CPU跨切循环层的次数。

五、函数设计

5.1 参数的规则

1.参数的书写要完整,不要贪图省事只写参数的类型而省略参数名字。如果函数没有参数,则用void填充。
例如:

void SetValue(int width, int height); // 良好的风格
void SetValue(int, int); // 不良的风格
float GetValue(void);   // 良好的风格
float GetValue(); // 不良的风格
2.参数命名要恰当,顺序要合理。

例如:

void StringCopy(char *str1, char *str2); // 不良的风格
void StringCopy(char *strSource,char *strDestination);// 良好的风格
3.如果参数是指针,且仅作输入用,则应在类型前加const,以防止该指针在函数体内被意外修改。
例如:
void StringCopy(char *strDestination,const char *strSource); 
5.2 返回值的规则
1.不要省略返回值的类型。
2.C语言中,凡不加类型说明的函数,一律自动按整型处理。这样做不会有什么好处,却容易被误解为void类型。C++语言有很严格的类型安全检查,不允许上述情况发生。由于C++程序可以调用C函数,为了避免混乱,规定任何C++/ C函数都必须有类型。如果函数没有返回值,那么应声明为void类型。
不要将正常值和错误标志混在一起返回。正常值用输出参数获得,而错误标志用return语句返回。

3.有时候函数原本不需要返回值,但为了增加灵活性如支持链式表达,可以附加返回值。例如字符串拷贝函数strcpy的原型:

char *strcpy(char *strDest,const char *strSrc); 
strcpy函数将strSrc拷贝至输出参数strDest中,同时函数的返回值又是strDest。这样做并非多此一举,可以获得如下灵活性:
 char str[20]; 
 int   length = strlen( strcpy(str, “Hello World”) ); 
5.3 函数内部实现的规则

1.在函数体的“入口处”,对参数的有效性进行检查。很多程序错误是由非法参数引起的,我们应该充分理解并正确使用“断言”(assert)来防止此类错误。
2.在函数体的“出口处”,对return语句的正确性和效率进行检查。

3.函数的功能要单一,不要设计多用途的函数。

4.函数体的规模要小,尽量控制在50行代码之内。

5.4使用断言

1.使用断言捕捉不应该发生的非法情况。

2.在函数的入口处,使用断言检查参数的有效性(合法性)。


六、内存管理

6.1内存分配方式
1.内存分配方式有三种:
(1)  从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。
(2)  在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
(3)  从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活。

2.用malloc或new申请内存之后,应该立即检查指针值是否为NULL。
防止使用指针值为NULL的内存。

3.用free或delete释放了内存之后,立即将指针设置为NULL,防止产
生“野指针”。

6.2有了malloc/free为什么还要new/delete ?

  malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。

    类Obj的函数Initialize模拟了构造函数的功能,函数Destroy模拟了析构函数的功能。函数UseMallocFree中,由于malloc/free不能执行构造函数与析构函数,必须调用成员函数Initialize和Destroy来完成初始化与清除工作。函数UseNewDelete则简单得多。所以我们不要企图用malloc/free来完成动态对象的内存管理,应该用new/delete。由于内部数据类型的“对象”没有构造与析构的过程,对它们而言malloc/free和new/delete是等价的。既然new/delete的功能完全覆盖了malloc/free,为什么C++不把malloc/free淘汰出局呢?这是因为C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。如果用free释放“new创建的动态对象”,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放“malloc申请的动态内存”,理论上讲程序不会出错,但是该程序的可读性很差。所以new/delete必须配对使用,malloc/free也一样。












$(function(){ $.fn.extend({ SimpleTree:function(options){ //初始化参数 var option = $.extend({ click:function(a){ } },options); option.tree=this; /* 在参数对象中添加对当前菜单树的引用,以便在对象中使用该菜单树 */ option._init=function(){ /* * 初始化菜单展开状态,以及分叉节点的样式 */ this.tree.find("ul ul").hide(); /* 隐藏所有子级菜单 */ this.tree.find("ul ul").prev("li").removeClass("open"); /* 移除所有子级菜单父节点的 open 样式 */ this.tree.find("ul ul[show='true']").show(); /* 显示 show 属性为 true 的子级菜单 */ this.tree.find("ul ul[show='true']").prev("li").addClass("open"); /* 添加 show 属性为 true 的子级菜单父节点的 open 样式 */ }/* option._init() End */ /* 设置所有超链接不响应单击事件 */ this.find("a").click(function(){ $(this).parent("li").click(); return false; }); /* 菜单项 接受单击 */ this.find("li").click(function(){ /* * 当单击菜单项 * 1.触发用户自定义的单击事件,将该 标签中的第一个超链接做为参数传递过去 * 2.修改当前菜单项所属的子菜单的显示状态(如果等于 true 将其设置为 false,否则将其设置为 true) * 3.重新初始化菜单 */ option.click($(this).find("a")[0]); /* 触发单击 */ /* * 如果当前节点下面包含子菜单,并且其 show 属性的值为 true,则修改其 show 属性为 false * 否则修改其 show 属性为 true */ /* if($(this).next("ul").attr("show")=="true"){ $(this).next("ul").attr("show","false"); }else{ $(this).next("ul").attr("show","true"); }*/ /* 初始化菜单 */ option._init(); }); /* 设置所有父节点样式 */ this.find("ul").prev("li").addClass("folder"); /* 设置节点“是否包含子节点”属性 */ this.find("li").find("a").attr("hasChild",false); this.find("ul").prev("li").find("a").attr("hasChild",true); /* 初始化菜单 */ option._init(); }/* SimpleTree Function End */ }); });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值