Loading

C/C++ 编程规范

出自:高质量 C++/C 编程指南 作者:林锐

第1章 文件结构

1.1 版权和版权的声明

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

/*
* Copyright (c) 2001,上海贝尔有限公司网络应用事业部
* All rights reserved.
*
* 文件名称: filename.h
* 文件标识: 见配置管理计划书
* 摘 要: 简要描述本文件的内容
*
* 当前版本: 1.1
* 作 者: 输入作者(或修改者)名字
* 完成日期: 2001年7月20日
*
* 取代版本: 1.0
* 原作者 : 输入原作者(或修改者)名字
* 完成日期: 2001年5月10日
*/

1.2 头文件的结构

头文件由三部分内容组成:
(1)头文件开头处的版权和版本声明。
(2)预处理块。
(3)函数和类结构声明等。

【规则 1-2-1】为了防止头文件被重复引用,应当用 ifndef/define/endif 结构产生预处理块。

【规则 1-2-2】用 #include <filename.h> 格式来引用标准库的头文件(编译器将从标准库目录开始搜索)。

【规则 1-2-3】用 #include “filename.h” 格式来引用非标准库的头文件(编译器将从用户的工作目录开始搜索)。

【建议 1-2-1】头文件中只存放“声明”而不存放“定义”在 C++ 语法中,类的成员函数可以在声明的同时被定义,并且自动成为内联函数。这虽然会带来书写上的方便,但却造成了风格不一致,弊大于利。建议将成员函数的定义与声明分开,不论该函数体有多么小。

【建议 1-2-2】不提倡使用全局变量, 尽量不要在头文件中出现象 extern int value 这类声明。

1.3 定义文件的结构

定义文件有三部分内容:
(1) 定义文件开头处的版权和版本声明。
(2) 对一些头文件的引用。
(3) 程序的实现体(包括数据和代码)。

1.4 头文件的作用

(1)通过头文件来调用库功能。
(2)头文件能加强类型安全检查。

1.5 目录结构

如果一个软件的头文件数目比较多(如超过十个),通常应将头文件和定义文件分别保存于不同的目录,以便于维护。
例如可将头文件保存于 include 目录,将定义文件保存于 source 目录(可以是多级目录)。

第 2 章 程序的版式

2.1 空行

【规则 2-1-1】在每个类声明之后、每个函数定义结束之后都要加空行。

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

//空行
void Function1(···)
{
   statement1;
   // 空行
   if (condition)
   {
   statement2;
   }
   else
   {
   statement3;
}
   // 空行
   statement4;
}
//空行
void Function2(···)
{
   ···
}
//空行

2.2 代码行

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

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

int width; // 宽度
int height; // 高度
int depth; // 深度

x = a + b;
y = c + d;
z = e + f;

if (width < height)
{
   dosomething();
}

【建议 2-2-1】尽可能在定义变量的同时初始化该变量(就近原则)如果变量的引用处和其定义处相隔比较远,变量的初始化很容易被忘记。如果引用了未被初始化的变量,可能会导致程序错误。本建议可以减少隐患。例如

int width = 10; // 定义并初绐化 width
int height = 10; // 定义并初绐化 height
int depth = 10; // 定义并初绐化 depth

2.3 代码行内的空格

【规则 2-3-1】关键字之后要留空格。象 const、 virtual、 inline、 case 等关键字之后至少要留一个空格,否则无法辨析关键字。象 if、 for、 while 等关键字之后应留一个空格再跟左括号‘(’,以突出关键字。

【规则 2-3-2】函数名之后不要留空格,紧跟左括号‘(’,以与关键字区别。

【规则 2-3-3】‘(’向后紧跟,‘)’、‘,’、‘;’向前紧跟,紧跟处不留空格。

【规则 2-3-4】‘,’之后要留空格,如 Function(x, y, z)。如果‘;’不是一行的结束符号,其后要留空格,如 for (initialization; condition; update)。

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

【规则 2-3-6】一元操作符如“!”、“~”、“++”、“--”、“&”(地址运算符)等前后不加空格。

【规则 2-3-7】象“[]”、“.”、“->”这类操作符前后不加空格。

【建议 2-3-1】对于表达式比较长的 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-4-1】程序的分界符‘{’和‘}’应独占一行并且位于同一列,同时与引用它们的语句左对齐。

【规则 2-4-2】 { }之内的代码块在‘{’右边数格处左对齐。

void Function(int x)
{
   … // program code
}

2.5 长行拆分

【规则 2-5-1】代码行最大长度宜控制在 70 至 80 个字符以内。代码行不要过长,否则眼睛看不过来,也不便于打印。

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

2.6 修饰符的位置

【规则 2-6-1】应当将修饰符 * 和 & 紧靠变量名

2.7 注释

C语言的注释符为“//”。 C++语言中,程序块的注释常采用“//”,行注释一般采用“//…”。注释通常用于:
(1)版本、版权声明;
(2)函数接口说明;
(3)重要的代码行或段落提示。

【规则 2-7-1】注释是对代码的“提示”,而不是文档。程序中的注释不可喧宾夺主,注释太多了会让人眼花缭乱。注释的花样要少。

【规则 2-7-2】如果代码本来就是清楚的,则不必加注释。否则多此一举,令人厌烦。

【规则 2-7-3】边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。不再有用的注释要删除。

【规则 2-7-4】注释应当准确、易懂,防止注释有二义性。错误的注释不但无益反而有害。

【规则 2-7-5】尽量避免在注释中使用缩写,特别是不常用缩写。

【规则 2-7-6】注释的位置应与被描述的代码相邻,可以放在代码的上方或右方,不可放在下方。

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

2.8 类的版式

将 public 类型的函数写在前面,而将 private 类型的数据写在后面

class A
{
public:
void Func1(void);
void Func2(void);
…
private:
int i, j;
float x, y;
…
}

第3章 命名规则

3.1 共性规则

【规则 3-1-1】标识符应当直观且可以拼读,可望文知意,不必进行“解码”。标识符最好采用英文单词或其组合。

【规则 3-1-2】标识符的长度应当符合“min-length && max-information”原则。

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

【规则 3-1-4】程序中不要出现仅靠大小写区分的相似的标识符。例如:

int x, X; // 变量 x 与 X 容易混淆
void foo(int x); // 函数 foo 与 FOO 容易混淆
void FOO(float x);

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

【规则 3-1-6】变量的名字应当使用“名词”或者“形容词+名词”。例如:

float value;
float oldValue;
float newValue;

【规则 3-1-7】全局函数的名字应当使用“动词”或者“动词+名词”(动宾词组)。类的成员函数应当只使用“动词”,被省略掉的名词就是对象本身。例如:

DrawBox(); // 全局函数
box->Draw(); // 类的成员函数

【规则 3-1-8】用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。例如:

int minValue;
int maxValue;
int SetValue(…);
int GetValue(…);

【建议 3-1-1】尽量避免名字中出现数字编号,如 Value1,Value2 等,除非逻辑上的确需要编号。这是为了防止程序员偷懒,不肯为命名动脑筋而导致产生无意义的名字(因为用数字编号最省事)。

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

【规则 3-2-1】类名和函数名用大写字母开头的单词组合而成。例如:

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

【规则 3-2-2】变量和参数用小写字母开头的单词组合而成。例如:

BOOL flag;
int drawMode;

【规则 3-2-3】常量全用大写的字母,用下划线分割单词。例如:

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

【规则 3-2-4】静态变量加前缀 s_(表示 static)。例如:

void Init(…)
{
static int s_initValue; // 静态变量
…
}

【规则 3-2-5】如果不得已需要全局变量,则使全局变量加前缀 g_(表示 global)。例如:

int g_howManyPeople; // 全局变量
int g_howMuchMoney; // 全局变量

【规则 3-2-6】类的数据成员加前缀 m_(表示 member),这样可以避免数据成员与成员函数的参数同名。例如:

void Object::SetValue(int width, int height)
{
  m_width = width;
  m_height = height;
}

【规则 3-2-7】为了防止某一软件库中的一些标识符和其它软件库中的冲突,可以为各种标识符加上能反映软件性质的前缀。例如三维图形标准 OpenGL 的所有库函数均以 gl 开头,所有常量(或宏定义)均以 GL 开头。

posted @ 2020-08-20 21:44  小森林呐  阅读(214)  评论(0编辑  收藏  举报