10.4 虚基类
多基派生中,如果在多条继承路径上有一个共同的基类,如图10.4所示,从中不难看出,在D类对象中,会有来自两条不同路径的共同基类(类A)的双重复制。
10.4.1 共同基类带来的二义性
共同基类和多基派生的共同作用,使得在派生类中会出现多个共同基类的复制,这很容易带来二义性问题,如代码10.3所示。
图 10.4 多基继承时的共同基类问题
代码10.3 多基继承时的共同基类CommonBase
<———————————文件名:example1003.cpp———————————————-> 01 #include<iostream> 02 using namespace std; 03 class A//公共基类 04 { 05 protected://protected成员列表 06 int x; 07 public://public成员列表 08 A(int xp=0)//构造函数 09 { 10 x=xp; 11 } 12 void SetX(int xp)//设置protected成员x的值 13 { 14 x=xp; 15 } 16 void print() 17 { 18 cout<<"this is x in A:"<<x<<endl; 19 } 20 }; 21 class B:public A//类B由类A派生而来 22 { 23 }; 24 class C:public A//类C由类A派生而来 25 { 26 }; 27 class D:public B,public C//类D由类B和类C派生而来 28 { 29 }; 30 int main() 31 { 32 D exD;//声明一个D类对象exD 33 exD. SetX(5); 34 exD. print(); 35 return 0; 36 }编译运行,编译器提示错误信息如下所示。 error C2385:'D:SetX'is ambiguous error C2385:'D:print'is ambiguous
【代码解析】代码10.3中,由于类B和类C都是从类A派生而来的,因此,类B和类C的对象中都保存有一份类A的复制,因此,当代码第27行使用类B和类C派生类D时,编译器无法判断所调用的函数继承自B还是C,出现二义性错误,代码10.3的DAG图表示如图10.5所示。
图 10.5 共同基类引发二义性的DAG图表示