C# · 12月 20, 2021

C++编程规范 8-24章

第八章 常量

1.不要让常量成员函数修改程序的状态:不要修改成员、静态成员、、全局变量、其他对象。

第九章 重载

1.尽量避免重载宰模板类型上:可能存在二义性

第十章 操作符

1.区分作为成员函数和作为友元的操作符:operator+=()、operator=()等都需要左值,应是成员函数;而操作符operator==()、operator+()不需要左值,应是友元

操作符作为成员函数可以确保左值一定是类对象

操作符为友元,可以使第一个操作数可以使任意类型,不一定非要是自定义类

第十一章 类型转换

1.尽量避免强制类型转换,如果不得不强制转换,尽量用显示方式

2.用虚函数方式取代dynamic_cast

虚函数不需要再编码时确定对象的真实类型,而dynamic_cast必须告知要转成的类型,运行时若类型不当还要抛出一个异常,所以还需提供失败检测机制。

虚函数的执行效率远高于dynamic_cast,因为dynamic_cast的转换机制比虚函数复杂

当增加或删除一个派生类时,dynamic_cast用法还得增减相应的代码

提供完善的dynamic_cast失败检测机制非常困难

3.使用关键字explicit防止单参数构造函数的类型转换功能

4.避免多个函数提供相同的类型转换

第十二章 友元

1.少用友元

类间高耦合

降低可继承性

第十三章 模板

滥用模板会造成的后果:

代码过度膨胀

不好修改,容易引发“蝴蝶效应”

很难确保能正常工作

1.使用模板如果有限制条件一定要注释或在文档中描述清楚

2.模板类型应传引用/指针而不是值

3.模板的特殊性

延迟编译,导致错误被隐藏:模板是在实例化的时候才编译

增加编译时间:实例化模板是指代码中用具体的类替换模板

模板的错误提示比较晦涩

中断编译可能导致错误

第十四章 表达式和控制流程

1.让表达式直观

2.避免对浮点类型做 == 或 != 判断

第十五章 宏

1.彻底用常量替代(类似功能的)宏

2.彻底用inline函数替代宏函数

3.函数宏的每个参数都要括起来

4.不带参数的宏函数也要定义成函数形式

5.用{}将函数宏的函数体括起来

6.不要在公共头文件中定义宏

第十六章 异常处理

1.确保代码在异常出现时能正确处理

系统异常,要么意味着程序有错,要么意味着资源不够

异常处理代价很高,所以对无能为力的系统异常,不予考虑是明智的

自定义的异常却要扩散出去让别人处理,应先事先约定好,所以必须有文字描述

2.正确注释代码的异常处理能力

不扩散

扩散

不知道

3.特别当心析构时发生异常

C++的异常处理机制规定,若在异常处理期间又发生异常,程序将被终止

如果析构时发生异常,而这个异常又不能被该析构函数处理,则导致该析构函数被打断

4.捕捉异常时绝不要先基类后派生类

5.捕捉异常时用引用

如果是拷贝,可能拷贝不成功

拷贝不能得到派生类对象,因为在拷贝时,派生类对象会被切削成基类

如果是指针,用完之后是否需要清除?

需要判断指针是空吗?如何知道该指针所指对象是否还有效

第十七章 代码格式

1.若某个case不需要break一定要注释声明

第十八章 注释

1.尽量用英文写注释

2.不要用/**/注释掉大块代码,应该用#if()

第十九章 文件和目录

第二十章 头文件

1.头文件多次引用的防范

#ifndef MY_CLASS_HPP

#define MY_CLASS_HPP

#endif

2.不要在头文件中定义常量/变量

3.任何声明若被多个源文件引用则应在一个头文件中

第二十一章 条件编译

1.若使用#if或#ifdef,不要遗漏#else

确保条件 编译的完整性

使得编译条件选择错误出现在编译时而不是运行时

第二十二章 编译

1.减少文件的依赖程度

第二十三章 兼容性

1.运算时显示转换有符号和无符号类型

2.注意双字节字符的兼容性

3.不要强制引用/指针指向尺寸不同的目标

4.不要假设不同源文件中静态或全局变量的初始化顺序

5.注意数据文件的兼容性

字节排列顺序

数据对齐

行尾标志

6.注意引用公共库的兼容性

7.代码中用到的路径只用“ / ”而不要用“ ”

8.确保main()函数总是返回一个类型

9.不要依赖pragmas

第二十四章 性能

1.不要用移位代替乘除运算

2.返回直接构造临时变量