众所周知C++是支持多重继承的,而JAVA是只支持单继承的。多重继承的好处就是你可以从多个父类中继承多重特性,而坏处就是如果各父类中有相同的名称就非常容易造成歧义。
另外,在继承体系的路径上会出现交叉的情况,即像下面这种情况。
假设IOFile中有一个成员继承自InputFile和OutputFile,但是InputFile和OutputFile中的这个成员又继承自File,那么IOFile对象的成分中就会包含至少2份相同的父类的成分,而我们只需要一分即可,毫无疑问这会增加对象的体积,并且还会造成时间和空间的浪费。
为此C++提出了virtual继承的概念,如下图所示:
但是,问题来了。采用virtual继承的子类对象的体积会偏大,这是因为子类对象中需要额外包含一个虚指针,子类对象访问virtual父类数据成员时速度慢。当然这是相对于同种继承体系的非virtual继承而言的,因为这个过程是通过间接寻址来完成的。另外,最底层子类对象在初始化时还要负责对继承层次中的各virtual基类进行初始化无论基类有多远,这也会占用大量时间。
所以作者的建议是1、没必要的话别用virtual继承,2、你非要用的话,别在virtual基类中放数据成员。
在这里作者举了一个例子来说明多重继承的必要性。A是一个接口interface,它等着类B去实现A的各纯virtual函数,因此B是一个A,这满足IS-A的关系,因此需要采用public继承。但是B的实现需要用到许多类C中已经实现好的接口,也就是代码的重用,那么B和C之间的关系就是is-implemented-in-terms-of,它俩应该是private继承的关系,虽然复合也是可以采用的,但因为此时C含有virtual函数,所以还是采用private继承吧,何必费那个劲呢。这样B既public继承了A同时也private继承了C。
作者说如果单继承和多继承都能解决问题并且花费代价也都差不多,那就用单继承。但是有时候多继承确实是简洁、合理、易维护的,这时候你就应该使用多继承。
最后作者总结道:
1、多继承可能导致歧义,并且需要virtual继承;
2、virtual继承会增加对象大小,减慢速度,增加初始化复杂度等。如果非要使用virtual继承,那么virtual基类中最好不要放数据成员;
3、多继承也有其用场,比如说public继承interface并且private继承用来复用代码。