【高质量C/C++】2.程序的版式

【高质量C/C++】—— 2. 程序的版式
版式不会影响程序的功能,但是会影响程序的阅读性,阅读性不好的程序维护的成本是非常高的,所以一定要有良好的代码风格

一、代码的版式

1. 空行

空行有分隔程序的作用,会让程序布局更清晰。空行会占用一些源文件大小,但不影响编译后的可执行文件大小。

规则

  1. 每个 类声明后 和 函数定义 结束后都要加空行
  2. 在一个函数体,逻辑上密切相关的语句之间不加空行,其它地方应加空行分隔
// 函数之间的空行
void function1(... ...)
{
    ... ...
}
// 空行
void function2(... ...)
{
    ... ...
}
// 空行
void function3(... ...)
{
    ... ...
}
// 函数内部的空行
while (condition)
{
    statement1;
    // 空行
    if (condition)
    {
        statement2;
    }
    else
    {
        statement3;
    }
    // 空行
    statement4;
}

2. 代码行

规则

  1. 一行代码只做一件事。如只定义一个变量,只定义一个语句。这样的代码更容易阅读,更方便写注释。
  2. ifforwhiledo等语句独占一行,执行语句不要紧跟其后。不论多少语句执行都要加{}
// 良好的代码风格
int width;		// 宽度
int height;		// 高度
int depth;		// 深度

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

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

for (int i=0; i<n; i++)
{
    printf("%d ", i);
}

other();
// 风格不良的代码行
int width, height, depth;

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

if (width < height) dosomething();

for (int i=0; i<n; i++)
    printf("%d ", i);
other();

建议

  1. 尽可能在定义变量的时候同时初始化该变量,若是变量的引用处和定义相隔较远,就会忘记并使用未初始化的变量。
  2. 变量在初始化时若是没有马上要使用的值,则可以暂时赋值为0NULL(C++中为nullptr),这个建议非常有用,所以一般情况下请把它当作一个好的规则使用
int width = 10;		// 宽度
int height = 10;	// 高度
int depth = 10;		// 深度

int num = 0;
int* p = nullptr;

3. 代码行内的空格

规则

  1. 标识符(函数名和关键字):
    1. 关键字后要留空格,对于constinlinecase等关键字不留空格会使编译器无法辩析关键字,导致编译失败,这种情况众人皆知。重点是ifforwhile等关键字之后要留一个空格再跟左括号,以突出关键字。
    2. 函数名后面不要留空格,紧跟左括号,与关键字区别
if (year >= 2000)		// 良好的风格
	;
if(year >= 2000)		// 不良的风格
	;

void Function1(int x, int y, int z);	// 良好的风格
void Function2 (int x, int y, int z);	// 不良的风格
  1. 运算符:
    1. (向后紧跟,),;向前紧跟,紧跟处不留空格
    2. ,;如果不是一行的结束,则要留出空格
    3. 赋值、比较、算术、位域、逻辑等二元操作符的两侧应加空格。
    4. !~++--&(取地址)等一元操作符前后不加空格
    5. [].->这类操作符前后不加空格
if (year >= 2000)			// 良好的风格
	;
if (year>=2000)				// 不良的风格
    ;
if ( year >= 2000)			// 不良的风格
    ;
    
int i = 0;
i++;						// 良好的风格
i --;						// 不良的风格

&i;							// 良好的风格
~ i;						// 不良的风格

arr[5] = 0;					// 良好的风格
arr[ 5 ] = 0;				// 不良的风格

a.Function();				// 良好的风格
a . Function();				// 不良的风格

b->Function();				// 良好的风格
b -> Function();			// 不良的风格

for (int i = 0; i < n; i++)	// 良好的风格
    ;
for (int i=0; i<n; i++)		// 良好的风格,将逻辑紧密的语句写的紧凑也是一个不错的风格,推荐在表达式略复杂时使用
    ;
for (int i=0;i<n;i++)		// 不良的风格
    ;

建议

  • 表达式:
    1. 对于表达式比较长的for、if语句,为了紧凑起见可以适当去掉一些空格。
    2. 在长表达式中,建议使用括号将逻辑紧密的表达式括在一起,这样既保证运算符优先级,有保证层次清晰
int c = a < b ? a * b : a - b;
int d = a<b ? a*b : a-b;

if ((a<=b) && (c<=d))	// 良好的风格
    ;
if (a <= b && c <= d)	// 不良的风格
    ;

4. 对齐

规则

  1. 程序的分界符{ }独占一行且位于同一列,同时与引用它们的语句左对齐
  2. {}之内的代码应在{ 的下一行右边一个tab键的距离对齐
// 良好的风格
void Function1(int x)
{
    statement;
}

// 不良的风格
void Function2(int y) {
    statement;
}

// 良好的风格
if (condition)
{
    statement1;
}
else
{
    statement2;
}

// 不良的风格
if (condition) {
    statement1;
} else {
    statement2;
}

// 良好的风格
for (int i=0; i<n; i++)
{
    for (int j=0; j<n; j++)
    {
        statement;
    }
}

5. 长行拆分

规则

  1. 代码的最大长度控制在80个字符以内。代码过长会使眼睛看不过来,也不便打印
  2. 长表达式要在低优先级操作符处拆分成新行,操作符放在新行之首(突出操作符)。拆分的新行要适当缩进,排版整齐。
// 良好的风格
if ((very_long_variable1 >= very_long_variable2)
    && (very_long_variable3 <= very_long_variable4)
    && (very_long_variable5 == very_long_variable6))
{
    dosomething();
}

// 良好的风格
virtual CMatrix CMultiplyMatrix(CMatrix leftMatrix,
                                CMatrix rightMatrix);

// 良好的风格
for (very_long_initialization;
     very_long_condition;
     very_long_update)
{
    dosomething();
}

6. 修饰符位置

修饰符*&应该靠近数据类型还是靠近变量名,这是个有争议的话题。

修饰符靠近数据类型,如int* x从语义上看此写法比较直观,及x使int类型的指针。但是当此写法声明多个变量时容易引起误解,如int* x, y,使y容易被当作int*类型的指针。

规则

  • 修饰符*&应当紧靠变量名
char *name;
char *x, *y;

二、注释

C语言的注释符为/*注释内容*/,在C++中,程序块的注释通常采用/*注释内容*/,行注释一般采用//注释内容

注释通常用于:

  1. 版本、版权声明
  2. 函数接口说明
  3. 重要代码行或段落提示

规则

  1. 注释的花样要少。注释是对代码的提示,而不是文档,不可喧宾夺主,注释太多会让人眼花缭乱。如果代码本来就是清楚的,则不必要加注释,否则多此一举
  2. 边写代码边加注释,修改代码同时修改注释,保证注释与代码的一致性
  3. 注释应当准确、易懂,防止有二义性注释。错误的注释比不写注释更有害
  4. 尽量避免在注释中使用缩写,特别是不常用的缩写
  5. 注释的位置应与被描述的代码相邻,可以放在代码的上方或右方,不要放在下方
  6. 当代码比较长时,特别是多重嵌套,应当在一些段落的结束处加注释,便于阅读
/*
* 函数介绍:
* 输入参数:
* 输出参数:
* 返回值  :
*/
void Function(float x, float y, float z)
{
    if (... ...)
    {
        ... ...
        while (... ...)
        {
            ... ...
        } // end of while
        ... ...
    } //end of if
} //end of Function

三、类的版式

类的版式主要有2种:

  1. private类型的数据写在前面,而将public类型的函数写在后面,这种版式的程序员主张类的设计“以数据为中心”,重点关注类的内部结构
  2. public类型的函数写在前面,而将private类型的数据写在后面,这种版式的程序员主张类的设计“以行为为中心”,重点关注类应该提供什么样的接口

建议

  • 建议采用“以行为为中心”的书写方式。首先考虑类应该提供什么样的接口,这样不仅让自己在设计类的时候思路清晰,而且方便别人阅读,用户最关心的是接口,而不是一堆私有数据成员。
//以行为为中心的版式
class A
{
public:
    void Function1(void);
    void Function2(void);
    ... ...
private:
    int a;
    int b;
    ... ...
}
//以数据为中心的版式
class A
{
private:
    int a;
    int b;
    ... ...
public:
    void Function1(void);
    void Function2(void);
    ... ...
}

猜你喜欢

转载自blog.csdn.net/weixin_52811588/article/details/127003719