C++多重继承经常出现,下面我们来讨论一种比较特殊的多重继承方式--菱形继承。
问题的提出:我们定义了一个动物类A,由A又可以派生出水栖生活动物类B(鲨鱼、螃蟹等)和陆栖生活动物类C(狮子、老虎等),那么实际中又存在一种两栖动物D同时继承B类和C类并具有自己本身的特点(青蛙,变态发育)。那么我们如何来定义这四个类的继承关系呢?我们需要定义A、B、C、D四个类,让B类和C类都继承A类,让D类同时继承B类和C类如下图:
在A类中我们定义一个public成员变量a:
{
public :
int a;
};
class B : public A
{
};
class C : public A
{
};
那么B类通过public继承A类,也同样继承了A类中的成员变量a,C类通过public继承A类,也同样继承了A类中成员变量a。
#include "C.h"
int main( void )
{
B b;
C c;
b.a;
c.a;
return 0;
}
以上代码通过编译器编译可以通过。
但是由于D类同时public继承了C类和D类,那么也就是说,D类也继承了C类中的成员变量a。
int main( void )
{
D d;
d.a;
return 0;
}
以上代码编译不通过,出错信息为:
也就是说D类从C类继承来的成员变量a是d.B::A::a,而D类从C类继承来的成员变量a是d.C::A::a。于是两个a出现了歧义,系统不知道D类中的成员变量a是来自B类还是来自A类,即:菱形继承中的二义性。所以编译不通过。
为了解决多重继承的二义性,我们可以在B类继承A类和C类继承A类时采用virtual虚拟继承方式:
class B : public virtual A
{
};
class C : public virtual A
{
};
由于采用了虚拟继承方式,当继承关系中出现二义性时系统会自动将出现歧义的成员统一为一个虚拟的成员。我们再次编译如下代码:
int main( void )
{
D d;
d.a;
return 0;
}
系统成功编译通过,没有出现成员变量a的歧义。