在三层或者三层以上的继承中,声明一个对象时,可能会出现访问不明确的编译错误。以下举例说明这个问题。
现有四个类:FirstP (第一代产品类),SecondP1 (第二代产品系列1类),SecondP2 (第二代产品系列2类),ThirdP (第三代产品类),它们是三个层次的类。
这四个类的继承关系如下:SecondP1和SecondP2继承于FirstP类,ThirdP又同时继承了SecondP1和SecondP2。
建立类ThirdP的对象,m_ThirdP。从m_ThirdP到FirstP有两条路径,即ThirdP←SecondP1←FirstP和ThirdP←SecondP2←FirstP。
现在m_ThirdP要访问FirstP的数据成员m_iTest,两条路径皆可。当编译时,编译器不知走哪条路径,就会出现如下编译错误:
error C2385: 对“m_iTest”的访问不明确。
使用虚基类,则可以解决这个问题,那就是用virtual关键字把基类继承定义为虚拟的。这里将SecondP1和SecondP2的继承方式改为虚拟继承,那么m_ThirdP访问FirstP那里继承来的成员就不会有二义性了。
本例的关键代码如下:
class FirstP
{
public:
int m_iTest;
};
class SecondP1:virtual public FirstP
{
public:
void Show1(int iTest1)
{
printf("%d\n",iTest1);
}
};
class SecondP2:virtual public FirstP
{
public:
void Show2(int iTest2)
{
printf("%d\n",iTest2);
}
};
class ThirdP:public SecondP1,public SecondP2
{
public:
void SetTest(int n)
{
m_iTest=n;
}
void Show()
{
printf("%d\n",m_iTest);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
ThirdP m_ThirdP;
m_ThirdP.SetTest(10);
//调用FirstP类的成员m_iTest
m_ThirdP.Show(); //结果为10
//调用SecondP1的成员Show1()
m_ThirdP.Show1(80); //结果为80
//调用SecondP2的成员Show2()
m_ThirdP.Show2(100); //结果为100
return 0;
}