C++菱形继承问题
在C++中,什么叫做菱形继承问题(也可以叫钻石问题),怎么避免它?
假设我们有类B和类C,它们都继承了相同的类A。另外我们还有类D,类D通过多重继承机制继承了类B和类C。因为上述图表的形状类似于钻石(或者菱形),因此这个问题被形象地称为钻石问题(菱形继承问题)。现在,我们将上面的图表翻译成具体的代码:
#include<iostream> class Animal{ private: int weight; public: virtual int getWeight() { return this->weight; } }; class Tiger : public Animal{}; class Lion : public Animal{}; class Liger : public Tiger, public Lion{}; int main() { Liger lg; lg.getWeight(); }
在我们的继承结构中,我们可以看出Tiger和Lion类都继承自Animal基类。所以问题是:因为Liger多重继承了Tiger和Lion类,因此Liger类会有两份Animal类的成员(数据和方法),Liger对象"lg"会包含Animal基类的两个子对象。
所以,你会问Liger对象有两个Animal基类的子对象会出现什么问题?再看看上面的代码-调用"lg.getWeight()"将会导致一个编译错误。这是因为编译器并不知道是调用Tiger类的getWeight()还是调用Lion类的getWeight()。所以,调用getWeight方法是不明确的,因此不能通过编译。
解决方法一:
使用虚继承,C++会保证对于每个Liger对象,只有一个Animal类的子对象会被创建。
#include<iostream> class Animal{ private: int weight; public: virtual int getWeight() { return this->weight; } }; class Tiger : virtual public Animal{}; class Lion : virtual public Animal{}; class Liger : public Tiger, public Lion{}; int main() { Liger lg; lg.getWeight(); }
解决方法二:
指定域
#include<iostream> class Animal{ private: int weight; public: virtual int getWeight() { return this->weight; } }; class Tiger : public Animal{}; class Lion : public Animal{}; class Liger : public Tiger, public Lion{}; int main() { Liger lg; lg.Lion::getWeight(); }
当存在多继承时,虽然我们尽可能地保证不同类中地成员变量和成员函数命名不冲突,但是想菱形继承仍有可能发生。
所以我们应该尽可能少地使用多继承,只有在比较简单或者实在有必要时才使用,能用单一继承解决的问题就不要使用多继承。也正是这个原因,C++之后的很多面向对象的语言,例如Java、C#、PHP等,都不支持多继承。
参考链接:
个性签名:时间会解决一切