第八章 常量
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.返回直接构造临时变量