1. 为什么我们需要使用 inheritance 或 composition?
这两者的主要作用是 code reuse 。它们是实现这一目的的两种不同的方式。 Composition 是将其 他类的对象作为自己的成员,而 Inheritance 是将新创建的类作为 a type of existing class .
2. 当我们继承了某个类 A 时,我们并不能存取类 A 的私有成员。那么我们如何在子类中初始化父类中的私有成员呢? 另外,对于 composition ,我们并不能在构造函数中直接调用所包含对象的构造函数,那么我们有如何对这些成员进行初始化呢? 还有对于类中的 const 成员,我们也不能在构造函数内部对其进行初始化,那么我们有应该怎么办呢?
所有这些问题的解决方法就是: constructor initializer list
3. 对于 Inheritance ,如果你没有在 constructor initializer list 中初始化基类的成员的话,编译器会自动调用基类的缺省构造函数。而对于 composition 也一样,编译器也会自动调用各 member object 的缺省构造函数。那么它们的调用顺序是什么呢?是否有一定的规律?
对于类层次结构来说,构造函数是从 根类 开始的。对于每个类的内部,又是按照 成员的声明顺序 依次调用各成员的构造函数。 注意,各成员的构造函数的调用顺序并不受它在 constructor initializer list 中的顺序的影响。这是由 destructor 的调用顺序决定的。 destructor 的调用顺序与 constructor 的调用顺序完全相反。 如果各成员构造函数的调用顺序有不同 constructor 的影响的话,那 destructor 应该怎么办呢?毕竟我们的 destructor 只有一个而已,不可能对不同的 constructor 有不同的 destructor 吧。
4. 当使用 inheritance 的时候,我们可能会出现以下情况:即你所定义的函数的 signature 与基类的某个函数完全相同。此时,如果基类的对应函数为 virtual 的话,你就 override 了该函数,而如果基类的对应函数不是 virtual 的话,你就 redefine 了该函数。但是如果你所定义的函数只是与基类的某个函数的函数名相同的话,而你改变了该函数的返回值或者参数列表的话,那又如何解释呢?
当你 redefine 了基类的某个函数,或者改变了该函数的返回值或参数列表的话,基类的对应函数就会被 覆盖 ,也就是说你不能使用子类的对象调用基类的对应函数了。如果基类的对应函数又同时被 overloaded 了的话,也就是说该函数在基类有多个相同函数名不同 signature 的函数的话,其余的函数也会被 覆盖 。
5. 对于 inheritance, 一般来说,基类成员或函数都会被子类所继承。但是,仍然有些函数例外。也就是说在父类中的这些函数并不会被自动继承到子类中。这些函数有那些?以及为什么他们不被继承到子类中?
这样的函数主要包括三类: constructors, destructor, operator= 。对于 constructors, destructor 而言,他们都是涉及到具体对象创建问题的。而对于不同的类,即使他们具有上下位的关系,他们的创建过程或析取过程也是不相同的。也就是说,父类的创建过程并不适用与子类的创建。另外, operator= 也具有对象创建的性质,所以他也不会被继承到子类中。
6. static 成员函数与普通的成员函数是不同的。那么在 inheritance 时,这些函数是否也会被继承到子类中呢?它在 inheritance 的相关问题上与普通的成员函数有什么区别呢?
大致来说, static 成员函数与普通成员函数在 inheritance 的相关问题上都是相同的,比如 static 成员函数也会继承到子类中。只有一点不同,那就是 static 成员函数不能是 virtual 的。
7. inheritance 和 composition 它们两者有什么区别吗?
他们两者的能力几乎是一样的。主要区别就是在 你所需表达的概念上 。如果你需要的只是现有类的某种能力,而不是该类的接口,也就是说你只是需要现有类来做某种事情,而你创建的类与该类并没有类似的接口的话,你就应该使用 composition 。而 inheritance 的应用正好相反。也就是说你需要的是现有类的接口,也就是你希望在可以使用现有类的地方,也可以使用你新创建的类,那么这是你就应该是用 inheritance. Inheritance 的另外一个好处就是子类可以 upcast 到基类。 upcast 的作用就是在所有使用父类的地方你都可以使用子类(除非你使用的是 private 继承) 。这是因为子类继承了父类中的所有成员(除了一些特殊情况)。所以另外一个决定是使用 composition 或 inheritance 的方式就是问一下问题:你是否需要从新建的类 upcast 。