Inheritance and Composition
为什么使用Inheritance和composition? 可以更好的重用已有的代码。可以在不修改已有代码的条件下重用已有的代码。
如何选择:Inheritance或composition?
- Inheritance: 关系是"is a";需要upcasting;
- Composition: 关系是"has a";需要的是subobject的功能,不需要保留其接口;
Initialization Sequence
使用 constructor initializer list 对基类或成员对象进行初始化。初始化的顺序:
1) 先基类,后派生类;
2) 同一个类中,先成员对象,后类的构造函数;
3) 类成员的初始化顺序按照对象声明的顺序;
说明:如果用成员对象的值给子类初始化,那么这个初始值是无效的。因为子类初始化的时候,成员对象还没有初始化。
Name hiding
在继承关系中有两种重新定义函数情况:
1) overriding
结合虚函数机制实现动态联编。这种情况下,不允许修改函数的参数和返回值类型。
2) overload/redefing
如果在派生类中定义了重新定义了基类中的函数,那么基类中的同名函数将在派生类中隐藏。
为什么这样设计?因为继承机制描述的是“is a”关系,派生类和基类应该有相同的行为。如果在派生类中重新定义了函数,也就表明希望有不同的行为,所以要隐藏基类中的同名函数。
不能自动继承的函数
- constructor/deconstructor
- operator=
继承关系中的Copy constructor
参见Copy constuctor
继承关系中的 Private
Private适用的场合:
1) 部分使用基类中的接口。将需要适用的接口使用using 声明。如果不需要适用基类的接口,应该考虑使用Composition。
2) 可以消除继承关系中的二义性;
继承关系中的二义性
通过::消除,例如:D d; d.B::a;
Upcasting
- 是从派生类到基类的转换。
- 适用于pointer和Reference。
- 不需要显式的使用类型转换。