条款 32: 确定你的 public 继承塑模出 is-a 关系
"public 继承"意味 is-a。适用于 base classes 身上的每一件事情一定也适用于derived classes 身上,因为每一个 derived class 对象也都是一个 base class 对象。
个人理解:基类的函数适用于派生类的每一个函数。
条款 33: 避免遮掩继承而来的名称
derived classes 内的名称会遮掩 base classes 内的名称。在 public 继承下从来没有人希望如此。
为了让被遮掩的名称再见天日,可使用 using 声明式或转交函数( forwarding functions)。
个人理解:相同名称会有覆盖的问题,public 继承可以用using 声明, private函数可以使用转交函数。
条款 34: 区分接口继承和实现继承
接口继承和实现继承不同。在 public 继承之下, derived classes 总是继承 base class的接口。
pure virtual 函数只具体指定接口继承。
简朴的(非纯) impure virtual 函数具体指定接口继承及缺省实现继承。
non-virtual 函数具体指定接口继承以及强制性实现继承。
个人理解:接口继承只继承函数接口,实现继承继承接口和实现、并且又能够重写;
条款 35: 考虑 virtual 函数以外的其他选择
virtual 函数的替代方案包括 NVl 手法及 Strategy 设计模式的多种形式。 NVI 于法自身是一个特殊形式的 Template Method 设计模式.
将机能从成员函数移到 class 外部函数,带来的一个缺点是,非成员函数无法访问 class 的 non-public 成员。
std::function 对象的行为就像→般函数指针。这样的对象可接纳"与给定之目标签名式 (target signature) 兼容"的所有可调用物 (callable entities)。
个人理解:
使用NVI手法,他是用public non-virtual成员函数包裹较低访问性(private和protected)
的virtual函数;
将virtual函数替换成“函数指针成员变量”,这是strategy设计模式的一种表现形式;
****以tr1::function成员变量替换virtual函数,因而允许使用任何可调用物(callable entity)
搭配一个兼容与需求的签名式,这也是strategy设计模式的某种形式;
将继承体系内的virtual函数替换成另一个继承体系内的virtual函数。这是strategy设计模式的传统做法;
条款 36: 绝不重新定义继承而来的 non-virtual 函数
绝对不要重新定义继承而来的 non-virtual 函数
个人理解:继承类会覆盖基类中函数实现;
条款 37: 绝不重新定义继承而来的缺省参数值
绝对不要重新定义一个继承而来的缺省参数值,因为缺省参数值都是静态绑定,而virtual函数一一你唯一应该覆写的东西一一却是动态绑定。
个人理解:
class Shape{
public:
enum ShapeColor {Red, Green, Blue};
virtual void draw(ShapeColor color=Red) const = 0;
};
class Rectangle : public Shape{
public:
virtual void draw(ShapeColor color=Green) const;//和父类的默认参数不同
}
Shape* pr = new Rectangle; // 注意此时pr的静态类型是Shape,但是他的动态类型是Rectangle
pr->draw(); //virtual函数是动态绑定,而缺省参数值是静态绑定,**所以会调用Red,而不是green**
class Rectangle : public Shape{
public:
virtual void draw(ShapeColor color= Red) const; //**(代码重复且带有相依性,不可取)**
}
**//可以更换为NVI的手法可以实现目的**
class Shape{
public:
enum ShapeColor {Red, Green, Blue};
void draw(ShapeColor color=Red) const {
doDraw();
}
private:
virtual void doDraw(ShapeColor color) const = 0;
};
class Rectangle : public Shape{
public:
virtual void doDraw(ShapeColor color) const;
}
条款 38: 通过复合塑模出 has-a 或"根据某物实现出”
复合( composition) 的意义和 public 继承完全不同。
在应用域 (application domain) ,复含意味 has -a (有一个)。在实现域(implementation domain) ,复合意味 is-implemented-in-terms-of(根据某物实现出)。
个人理解:
//应用领域:
class Address {...};
class PhoneNumber {...};
class Person {
...
private:
std::string name;
Address address;
PhoneNumber phone;
}
//实现域:set并不是一个list,但是set可以has a list:
template<class T>
class Set{
public:
void insert();
//.......
private:
std::list<T> rep;
}
条款 39: 明智而审慎地使用 private 继承
Private 继承意味 is-implemented-in-terms of (根据某物实现出)。它通常比复合(composition) 的级别低。但是当 derived class 需要访问 protected base class 的成员,或需要重新定义继承而来的virtual 函数时,这么设计是合理的。
和复合( composition) 不同, private 继承可以造成 empty base 最优化。这对致力于"对象尺寸最小化"的程序库开发者而言,可能很重要。
个人理解:如果D以private形式继承B,private继承意味着只有实现部分被继承,而没有其他含义。尽可能的使用复合,必要时才使用private(总结中提到的两种情况)
条款 40: 明智而审慎地使用多重继承
多重继承比单一继承复杂。它可能导致新的歧义性,以及对 virtual 继承的需要。
virtual 继承会增加大小、速度、初始化(及赋值)复杂度等等成本。如果 virtual base classes 不带任何数据,将是最具实用价值的情况。
多重继承的确有正当用途。其中一个情节涉及"public 继承某个 Interface class" 和 "private 继承某个协助实现的class" 的两相组合。
个人理解:多重继承基类对象存在多个