转载内容。另有其他更好的转载参考资料,在博文最末尾。
面向对象编程语言中的多重继承指的是一个类别可以同时从多于一个父类继承行为与特征的功能。与单一继承相对,单一继承指一个类别只可以继承自一个父类。
重温Java,发现Java竟然不支持类多重继承(直接继承类),却允许接口的多重继承。。
C++中类可以多重继承,Java中为什么不实现这个功能呢?多重继承会带来哪些问题,从而导致Java放弃类的多重继承?
再一深究,发现多年以来,多重继承一直是个敏感话题,赞成者看到的是免去笨拙的混合继承的利处,反对者看到的是多处混淆的弊端,例如变量的二义性,并且是多个变量。所以关于它的好处与风险之间孰轻孰重成为OO界多年争论的焦点。
其实最大的问题是出现拓补图,也就是出现钻石型继承结构(DOD),个人感觉这是个致命伤。正如其名:Diamond of Death。
举个简单的例子:
比如一个基类:动物。它有三个派生类:哺乳类动物,卡通类动物,宠物(确实都形成ISA关系)。现在有一个子类猫,从关系上推,它可以继承自哺乳类,卡通类,宠物,都符合ISA,如果要体现所有的特性,就需要全部继承,这样就形成了多重继承,却也形成了DOD,这样以后问题就出现了,从猫到动物的继承有三条路径,如果哺乳类,卡通类与宠物类中有相同的成员函数或变量,这样的数据组织方式会形成多义。
C++怎么解决这个问题的呢?虚继承。结果就是不得不牺牲一些内存开销,因为一个功能要在多处被重写。并且函数表里的函数指针必须调整,这样即使可以满足功能,在后期的维护也很复杂。
所以,Java才会采用这样折中的方法,硬生生的将类多重继承题了出去。
并且,网上也有不少建议,要尽可能避免多重继承,不惜一切代价去避免钻石结构,以避免后期不可挽回的大返工。
多重继承的概念:C++允许为一个派生类指定多个基类,这样的继承结构被称做多重继承。
举个例子,交通工具类可以派生出汽车和船连个子类,但拥有汽车和船共同特性水陆两用汽车就必须继承来自汽车类与船类的共同属性。
由此我们不难想出如下的图例与代码:
当一个派生类要使用多重继承的时候,必须在派生类名和冒号之后列出所有基类的类名,并用逗好分隔。
//程序作者:管宁
//站点:www.cndev-lab.com
//所有稿件均有版权,如要转载,请务必著名出处和作者
#include <iostream>
using namespace std;
class Vehicle
{
public:
Vehicle(int weight = 0)
{
Vehicle::weight = weight;
}
void SetWeight(int weight)
{
cout<<"重新设置重量"<<endl;
Vehicle::weight = weight;
}
virtual void ShowMe() = 0;
protected:
int weight;
};
class Car:public Vehicle//汽车
{
public:
Car(int weight=0,int aird=0):Vehicle(weight)
{
Car::aird = aird;
}
void ShowMe()
{
cout<<"我是汽车!"<<endl;