条款31:将文件间编译依存关系降至最低
请记住:
- 支持”编译依存性最小化“的一般构想是:相依于声明式,不要相依于定义式。基于此构想的两个手段是Handle class和Interface class
- 程序库头文件应该以”完全且仅有声明式“的形式存在。这种做法不论是否涉及template都适用
pimpl手法:在一个类中存放具体实现类的指针。这样,指针大小在32位系统上固定是4字节,无需知道具体实现类的大小。这解决了”接口与实现的分离“。是一种Handle class。
降低编译依存关系:
- 如果使用object reference或object pointers可以完成任务,就不要使用objects
- 如果能够,尽量以class声明替换class定义
- 为声明式和定义式提供不同的头文件
抽象基类是interface class。
Handle class和Interface class可降低编译依存性。
条款32:确定你的 public 继承塑模出 is-a 关系
请记住:
- public继承意味着is-a。适用于base class身上的每一件事一定也适用于derived class身上,因为每一个derived class对象也都是一个base class对象。
条款33:避免遮掩继承而来的名称
内层作用域的名称会遮掩外围作用域的名称
请记住:
- derived class内的名称会遮掩base class内的名称(一般是一个类中同名函数多个重载的情况)。在public继承下从来没有人希望如此。
- 为了让被遮掩的名称重见天日,可使用using声明式或转交函数(有一点理解,using)。
如果只想继承父类的部分函数,就可以使用private继承,然后设置一个转交函数,转交函数中使用父类作用域调用父类函数。
条款中,父类有多个重载函数的的情况,不论是虚函数还是非虚函数,都会发生遮掩。
using 可以帮助我们获得base 中被遮掩的函数,但是如果我们只想要多个重载函数中的一个而不是全部的时候该怎么办呢?可以写一个简单的转交函数:
条款34:区分接口继承和实现继承
请记住:
- 接口继承和实现继承不同。在 public 继承之下,derived classes 总是继承 base class 的接口
- pure virtual 函数只具体指定接口继承
- 简朴的(非纯)impure virtual 函数具体指定接口继承及缺省实现继承
- non-virtual 函数具体指定接口继承以及强制性实现继承
条款35:考虑 virtual 函数以外的其他选择
-
NVI手法:non-virtual interface
条款36:绝不重新定义继承而来的 non-virtual 函数
请记住:
- 绝不重新定义继承而来的non-virtual函数
- 为什么?因为,重新定义non-virtual函数会打破is-a的关系。
条款37:绝不重新定义继承而来的缺省参数值
对象的所谓静态类型(static type)就是它在程序中被声明时所采用的类型
virtual 函数是动态绑定的,但是缺省参数却是静态绑定的。意思是你可能会在“调用一个定义于 derived class”内的 virtual 函数的同时,却使用 base class 为它所指定的缺省参数值
请记住:
- 绝对不要重新定义一个继承而来的缺省参数值,因为缺省参数值都是静态绑定,而 virtual 函数--你唯一应该覆写的东西--却是动态绑定
条款38:通过复合塑模出 has-a 或“根据某物实现出”
参考文章:《Effective C++》笔记_effectivec++ 笔记-CSDN博客