IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 高质量C++/C指南笔记 -> 正文阅读

[C++知识库]高质量C++/C指南笔记

程序的版式

1.头文件

  • 头文件(.h)
    写类的声明(包括类里面的成员和方法的声明)、函数原型、#define常数等,但一 般来说不写出具体的实现。
  • 在写头文件时需要注意,在开头和结尾处必须按照如下样式加上预编译语句
#ifndef CIRCLE_H
#define CIRCLE_H
 
class Circle
{
private:
    double r;//半径
public:
    Circle();//构造函数
    Circle(double R);//构造函数
    double Area();//求面积函数
};
 
#endif

2-1?空行

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

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

// 空行
while (condition)
{
    statement1;
    // 空行
    if (condition)
    {
        statement2;
    }
    else
    {
        statement3;
    }
    // 空行
    statement4;
    }

2-2代码行

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

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

2-2-3?尽可能在定义变量的同时初始化该变量(就近原则)

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

void Func1(int x, int y, int z); // 良好的风格
if (year >= 2000) // 良好的风格
if ((a>=b) && (c<=d)) // 良好的风格
for (i=0; i<10; i++) // 良好的风格
x = a < b ? a : b; // 良好的风格
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】{ }之内的代码块在‘{’右边数格处左对齐。

2.5 长行拆分

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

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

for (very_longer_initialization;
    very_longer_condition;
    very_longer_update)
{
    dosomething();
}

2.6 修饰符的位置

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

char *name;
int *x, y; // 此处y不会被误解为指针

2.7 注释

注释通常用于:
(1)版本、版权声明;
(2)函数接口说明;
(3)重要的代码行或段落提示。

【规则2-7-1】注释是对代码的“提示”,而不是文档

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

【规则2-7-4】注释应当准确、易懂,防止注释有二义性。

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

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

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

/*
* 函数介绍:
* 输入参数:
* 输出参数:
* 返回值:
*/
void Function(float x, float y, float z)
{
    ?
}


if (?)
{
    ?

    while (?)
    {
    ?
    } // end of while

    ?
    } // end of if

2.8 类的版式

类的版式主要有两种方式:
(1)将private类型的数据写在前面,而将public类型的函数写在后面,这种版式的程序员主张类的设计“以数据为中心”,重点关注类的内部结构。

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


(2)将public类型的函数写在前面,而将private类型的数据写在后面,这种版式的程序员主张类的设计“以行为为中心”,重点关注的是类应该提供什么样的接口(或服务)。

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

命名规则

【规则3-1-1】标识符应当直观且可以拼读,可望文知意,不必进行“解码”。不要把CurrentValue写成NowValue。

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

【规则3-1-3】命名规则尽量与所采用的操作系统或开发工具的风格保持一致。
例如Windows应用程序的标识符通常采用“大小写”混排的方式,如AddChild。而Unix应用程序的标识符通常采用“小写加下划线”的方式,如add_child。别把这两类风格混在一起用

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

【规则3-1-5】程序中不要出现标识符完全相同的局部变量和全局变量

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

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

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

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

【建议3-1-1】尽量避免名字中出现数字编号,如Value1,Value2等,除非逻辑上的确需要编号。

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

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

class LeafNode; // 类名

void SetValue(int value); // 函数名

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

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

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

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

static int? s_initValue; // 静态变量

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

int g_howManyPeople; // 全局变量

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

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

表达式和基本语句

4.1 运算符的优先级

【规则4-1-1】如果代码行中的运算符比较多,用括号确定表达式的操作顺序,避免使用默认的优先级。如?if ((a | b) && (a & c))

4.2 复合表达式

【规则4-2-1】不要编写太复杂的复合表达式。

【规则4-2-2】不要有多用途的复合表达式。

【规则4-2-3】不要把程序中的复合表达式与“真正的数学表达式”混淆。

4.3 if 语句

【规则4-3-1】不可将布尔变量直接与TRUE、FALSE或者1、0进行比较。

【规则4-3-2】应当将整型变量用“==”或“!=”直接与0比较。

【规则4-3-3】不可将浮点变量用“==”或“!=”与任何数字比较。

????????转化为
????????if ((x>=-EPSINON) && (x<=EPSINON))

【规则4-3-4】应当将指针变量用“==”或“!=”与NULL比较。

4.4 循环语句的效率

【建议4-4-1】在多重循环中,如果有可能,应当将最长的循环放在最内层,最短的循环放在最外层,以减少CPU跨切循环层的次数

for (col=0; col<5; col++ )
{
       for (row=0; row<100; row++)
    {
        sum = sum + a[row][col];
    }
}

4.5 for 语句的循环控制变量

【规则4-5-1】不可在for 循环体内修改循环变量,防止for 循环失去控制。

【建议4-5-1】建议for语句的循环控制变量的取值采用“半开半闭区间”写法。

????????for (int x=0; x<N; x++)

4.6 switch语句

【规则4-6-1】每个case语句的结尾不要忘了加break,否则将导致多个分支重叠

【规则4-6-2】不要忘记最后那个default分支。即使程序真的不需要default处理,也应该保留语句 default : break;

第5章常量

【规则5-1-1】尽量使用含义直观的常量来表示那些将在程序中多次出现的数字或字符串。

5.2 const 与 #define的比较?

1)const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误(边际效应)。
(2)有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试。

【规则5-2-1】在C++ 程序中只使用const常量而不使用宏常量,即const常量完全取代宏常量。

5.3 常量定义规则

【规则5-3-1】需要对外公开的常量放在头文件中,不需要对外公开的常量放在定义文件的头部。为便于管理,可以把不同模块的常量集中存放在一个公共的头文件中。

【规则5-3-2】如果某一常量与其它常量密切相关,应在定义中包含这种关系,而不应给出一些孤立的值。

5.4 类中的常量

不能在类声明中初始化const数据成员

class A
{?
const int SIZE = 100; // 错误,企图在类声明中初始化const数据成员
int array[SIZE]; // 错误,未知的SIZE
};


const数据成员的初始化只能在类构造函数的初始化表中进行,例如
c

lass A
{?
A(int size); // 构造函数
const int SIZE ;
};
A::A(int size) : SIZE(size) // 构造函数的初始化表
{
?
}
A a(100); // 对象 a 的SIZE值为100
A b(200); // 对象 b 的SIZE值为200


怎样才能建立在整个类中都恒定的常量呢?别指望const数据成员了,应该用类中的枚举常量来实现。例如

class A
{?
enum { SIZE1 = 100, SIZE2 = 200}; // 枚举常量
int array1[SIZE1];
int array2[SIZE2];
};


?

第6章函数设计

6.1 参数的规则
【规则6-1-1】参数的书写要完整,不要贪图省事只写参数的类型而省略参数名字。如果函数没有参数,则用void填充。

【规则6-1-2】参数命名要恰当,顺序要合理。一般地,应将目的参数放在前面,源参数放在后面。

void StringCopy(char *strDestination,char *strSource);

【规则6-1-3】如果参数是指针,且仅作输入用,则应在类型前加const,以防止该指针在函数体内被意外修改。

【规则6-1-4】如果输入参数以值传递的方式传递对象,则宜改用“const &”方式来传递,这样可以省去临时对象的构造和析构过程,从而提高效率。

【建议6-1-1】避免函数有太多的参数,参数个数尽量控制在5个以内。如果参数太多,在使用时容易将参数类型或顺序搞错。

【建议6-1-2】尽量不要使用类型和数目不确定的参数。

6.2 返回值的规则

【规则6-2-1】不要省略返回值的类型。

【规则6-2-2】函数名字与返回值类型在语义上不可冲突。

【建议6-2-1】有时候函数原本不需要返回值,但为了增加灵活性如支持链式表达,可以附加返回值。

第7章内存管理

无论用何种方式创建数组,都别忘了赋初值,即便是赋零值也不可省略,不要嫌麻烦。

【规则7-2-1】用malloc或new申请内存之后,应该立即检查指针值是否为NULL。防止使用指针值为NULL的内存。

【规则7-2-2】不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。

【规则7-2-3】避免数组或指针的下标越界,特别要当心发生“多1”或者“少1”操作。

【规则7-2-4】动态内存的申请与释放必须配对,防止内存泄漏。

【规则7-2-5】用free或delete释放了内存之后,立即将指针设置为NULL,防止产生“野指针”。

7.5 free和delete把指针怎么啦?
发现指针p被free以后其地址仍然不变(非NULL),只是该地址对应的内存是垃圾,p成了“野指针”。如果此时不把p设置为NULL,会让人误以为p是个合法的指针。

char *p = (char *) malloc(100);
strcpy(p, “hello”);
free(p); // p 所指的内存被释放,但是p所指的地址仍然不变

7.7 杜绝“野指针”
“野指针”不是NULL指针,是指向“垃圾”内存的指针。

“野指针”的成因主要有两种:
(1)指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。

(2)指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-13 11:17:51  更:2021-10-13 11:19:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:47:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码