effective C++ 3nd
条款1:视C++为一个语言联邦
1. C
用于C的基本特性。
2. 面向对象
封装、继承、多态、动态绑定、虚函数表
3. 泛型编程
模板函数、模板类。这一部分也是大部分人接触最少的。(参考模板模式)
4. STL 库
高效的使用C++完成算法功能。
条款2:尽量以const、enum、inline替换#define
1. 单纯的常量,使用const、enum 替代#define
2. 函数计算宏,用inline替代#define
以上两点都是基于#define的不灵活性,以及编译器不对#define进行类型检查的原因导致的。
条款3:尽可能使用const
1. 让编译器帮助检查,同时避免出乎意料的错误
函数参数、返回值、内部变量
条款4:确定对象使用前已先被初始化
因为C++不一定保证初始化变量,手动初始化可以避免出乎意料的错误。
条款5:了解C++默认编写并调用哪些函数
编译器默认构建了:缺省构造函数、缺省赋值构造函数、缺省复制构造函数,以及默认析构函数。
条款6:若不想使用编译器自动生成的函数,就该明确拒绝
好吧,这一点我没什么好说的,使用private就行。
条款7:为多态基类声明virtual析构函数
确保在多态的时候,父类引用指向子类对象的时候,析构函数可以通过vptr正确的释放资源。
条款8:别让异常逃离析构函数
1. 在析构函数中,不抛出异常,而吞下异常(进行处理或者终止程序)
2. 尽量把需要析构的资源可能抛出异常的,放到一个普通函数中,供用户调用。
否则容器中的类将可能无法正常释放。
条款9:绝不在构造和析构过程中调用virtual函数
多态时,构造和析构的过程中,虚函数的vptr指针指向当前类,而非实际子类。
条款10:令operator=返回一个reference to *this
返回引用,以确保正确的链式赋值
条款11:在operator=中实现“自我赋值”
主要涉及到对内存的理解,在自我赋值的时候,不要delete了对应的内存。
条款12:复制对象时勿忘其每一部分
抽取共同代码,而否包含调用关系。分清深浅拷贝,避免析构时的错误。
条款13:以对象管理资源
典型的应用就是智能指针了,条款13主要用于保证资源在析构函数中正确的被释放。
条款14:在资源管理类中小心coping行为
结合上一条款理解,主要保证正确的使用资源。如采用:引用计数,深拷贝,资源转移等手段。
条款15:在资源管理类中提供对原始资源的访问
确保类的封装不会导致对资源访问的限制。
条款16:成对使用new和delete时要采取相同形式
这没什么好说的。
条款17:以独立语句将newed对象置入智能指针
C++11 对智能指针进行了内置,但仍然建议使用该策略。
条款18:让接口容易被正确使用,不容易被误用
一致性,见名知意,良好的类型检查避免误用。
条款19:设计class犹如设计type
这一条涉及到了延展性,类图谱性。目前,不能有深刻的体会。
条款20:宁以pass-by-reference-to-const替换pass-by-value
用于函数的原则,避免使用复制构造函数的调用,类的重复构建以及销毁。但是STL是值传递的形式(深拷贝,避免互相影响)。
条款21:必须返回对象时,别妄想返回其reference
本条款主要用于考虑栈空间的局部性(堆中没有该问题)。
条款22:将成员变量声明为private
良好的封装性,访问的一致性(通过函数)。
条款23:宁以non-member、non-friend替换member函数
通过non-member、non-friend的函数的操作,避免了不必要的对于private成员的错误访问,体现更好的封装性。
条款24:若所有参数皆需要类型转换,请为此采用non-member函数
本条款主要考虑C++支持的隐式转换问题。实用性是否较弱?
条款25:考虑写出一个不抛出异常的swap函数
条款26:尽可能延后变量定义式的出现时间
避免不必要的变量定义占用资源,同时也将清晰思路。
条款27:尽量少做转型动作
1. const_cast : 移除常量性
2. dynamic_cast : 向下转型
3. reinterpret_cast : 不同类型间的转换(如指针和非指针)
4. static_cast : 执行任意的隐式转换和相反转换
reinterpret_cast<new_type>(expression)
dynamic_cast<new_type>(expression)
static_cast<new_type>(expression)
const_cast<new_type>(expression)
条款28:避免返回handles指向对象内部成分
增加封装性
条款29:为“异常安全”而努力是值得的
避免处理异常的时候,资源或者数据遭到破坏。
条款30:透彻了解inlining的里里外外
不存在循环,少量判断,无函数指针,直接复制,小型,类型检查。
条款31:将文件间的编译依存关系降至最低
解耦。
条款32:确定你的public继承塑模出is-a关系
现在的OOP的使用应该更强调has-a的关系,但是当你确定框架结构的时候,需要明确is-a的关系建立。
条款33:避免遮掩继承而来的名称
C++11 提供了override关键字,但是子类无法和父类重载,所以当父类定义多个重载函数时,子类覆盖一个,则覆盖全部。
条款34:区分接口继承和实现继承
1. 纯虚函数
2. 虚函数
3. 非虚函数
条款35:考虑virtual函数以外的其他选择
本条款主要讨论策略模式,这里没有过多研究。
条款36:绝不重新定义继承而来的non-virtual函数
结合条款33,避免对于父类同名函数的覆盖
条款37:绝不要重新定义继承而来的缺省参数值
因为缺省参数值是静态绑定的。所以你重新定义的话,父类引用还是无法使用子类对象相应的值。
条款38:通过复合塑模树has-a 或“根据某物实现出”
松耦合的设计思想。
条款39:明智而审慎的使用private继承
就是基本别用的意思
条款40:明智而审慎的使用多重继承
会引起歧义,除非你是使用多继承实现接口。
条款41:了解隐式接口和编译期多态
认识template
条款42:了解typename的双重意义
条款43:学习处理模板化基类内的名称
条款44:将与参数无关的代码抽离templates
尽可能的降低templates二次编译所生成的代码数量。
条款45:运用成员函数模板接受所有兼容类型
条款46:需要类型转换时请为模板定义非成员函数
条款47:请使用traits class表现类型信息
条款48:认识template元编程
执行于编译期
条款49:了解new-handler的行为
条款50:了解new和delete的合理替换时机
条款51:编写new和delete时需固守常规
如若该操作可能失败,故最好加入判断。
条款52:写了placement new也要写placement delete
一一对应
条款53:不要轻忽编译器的警告
条款54:让自己熟悉包括TR1在内的标准程序库
TR1是一份C++标准的文档,如目前的C++11,都是基于其发展的。本条约告诉我们关注C++的发展。
条款55:让自己熟悉Boost
一个强大的第三方扩展库,对C++的新标准的推动性。