菱形继承的定义如下,从Base出发,至AB汇合,因此成为菱形继承。
class Base;
class SubA : public Base;
class SubB : public Base;
class AB : public SubA, public SubB;
这会导致两个问题:
1.二义性 , 如果 Base定义了一个函数 fun, 在AB中调用fun时,编译器将不知道你想调用哪个fun,是从SubA继承的还是从SubB继承的呢?
2.多个基类副本,SubA和SubB都含有Base的实例,这样,AB的实例中就存在两个Base实例,浪费了内存空间,继承链路越多,浪费的越多
处理方法:
1.在AB调用Base的fun时,指明继承链路,如: AB ab;ab.SubA::fun(); 这样就祛除了二义性
2.第一种方法能够祛除二义性,但基类的副本仍然是多个,这时就需要用到“虚继承”
其用法就是在继承链路的中间层,加上virtual,将前面的代码改为如下定义:
class Base;
class SubA : virtual public Base;
class SubB : virtual public Base;
class AB : public SubA, public SubB;
这时再编译 AB ab;ab.fun();就没问题了。
使用虚继承,不仅可以祛除二义性,还可以使得Base实例在AB中只有一份。