多重继承的存在有其合理性,但是在使用多重继承的时候也要注意存在的问题
1.一个派生类可能从多个基类继承相同的名称(函数、typedef等等),这会导致较多的歧义
例子:
#include<iostream>using namespace std;class base1{public:void fun1();void fun2();};class base2{public:void fun1();void fun3();};class Derived :public base1, public base2{};int main(){Derived d;//d.fun1(); //error C2385 : 对“fun1”的访问不明确// 可能是“fun1”(位于基“base1”中)// 也可能是“fun1”(位于基“base2”中)return 0;}
Derived public继承自base1和base2,由于两个基类中存在同名的函数fun1,所以在调用fun1时就出现了歧义,不知道调用的是哪一个,我们可以这样调用
d.base1::fun1();
所以多重继承可能会导致歧义,就算base的fun1()改为private,也不能阻止这种错误。因为C++首先是确认函数的最佳匹配而后才检验其可取性。在基类调用时发现两个相同匹配程度的函数,产生歧义。
2.多重继承导致菱形继承问题
如果B,C继承自A,D又继承自B,C(都是public继承),如上图,
#include<iostream>using namespace std;class A{public:void fun();private:int b;};class B:public A{private:int b1;};class C :public A{private:int b2;};class D :public B, public C{};int main(){D d;d.fun(); //error C2385 : 对“fun”的访问不明确//可能是“fun”(位于基“A”中)// 也可能是“fun”(位于基“A”中)return 0;}
运行胆码会发现调用fun函数产生歧义,错误信息是两个一模一样的fun位于基A中,原因是这种继承导致D从B和C中继承了A,解决办法就是让B和C virtual public继承自A,这虽然可以解决D中存在两份A的问题。
class B:virtual public A{private:int b1;};class C :virtual public A{private:int b2;};class D :public B, public C{};
但是virtual继承会增加对象的体积,是成员访问速度变慢等等,并且virtual 基类的初始化由继承体系中的最底层负责,这里A的初始化由D负责。
尽量不要使用虚基类,如果必须使用,不要在虚基类中放置数据。
多重继承也有其存在的合理性,用public继承接口,用private继承协助实现,这种多重继承的组合书上写了一个例子。所以说多重继承可以使用但是要明智而审慎地使用它
请记住:
1.多重继承比单一继承复杂。它可能导致新的歧义性,以及对virtual继承的需要。
2.virtual继承会增加大小、速度、初始化(及赋值)复杂度等等成本。如果virtual base classes 不带任何数据,将是最具有实用价值的情况。
3.多重继承的确有正当用途。其中一个情节涉及“public继承某个Interface class”和“private继承某个协助实现的class”的两相组合。