多重继承的存在有其合理性,但是在使用多重继承的时候也要注意存在的问题
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”的两相组合。