今天看到一本书上有关于虚基类的实现,看了之后猛然发现,自己以前在项目中也遇到这样的问题。当时不明白原因,只是通过别的方式解决了。其实核心思想就是由于多个父类造成的。看上面的用例关系图,一般的实现方式如下:
1、父类CBase的实现
//Base.h
Class CBase
{
public:
CBase();
virtual ~CBase();
protected:
void fun1();
}
//Base.cpp
#include "Base.h"
#include <iostream.h>
CBase::CBase()
{
}
CBase::~CBase()
{
}
void CBase::fun1()
{
cout<<"CBase Class..."<<endl;
}
2、子类CSubA、CSubB的实现
SubA.h
Class CSubA:public CBase
{
public:
CSubA();
virtual ~CSubA();
}
//SubA.mpp
#include "SubA.h"
CSubA::CSubA()
{
}
CSubA::~CSubA()
{
}
//子类CSubB的实现与CSubA类似不累述。
3、子子类CSubSubC
//CSubSubC.h
Class CSubSubC:public CSubA, public CSubB
{
public:
CSubSubC();
virtual ~CSubSubC();
void fun3();
}
//CSubSubC.cpp
#include "SubSubC.h"
#include <iostream.h>
CSubSubC::CSubSubC()
{
}
CSubSubC::~CSubSubC()
{
}
void CSubSubC::fun3()
{
cout<<"CSubSubC Class..."<<endl;
}
4、客户端实现main.cpp
#include "Base.h"
#include "SubA.h"
#include "SubB.h"
#include "SubSubC.h"
int main()
{
CSubSubC sub;
sub.fun3();
return 0;
}
总结:程序能够正常编译执行。
问题1:若在客户端通过CSubSubC的对象调用父类方法fun1()会怎样呢?
修改代码如下:
int main()
{
CSubSubC sub;
sub.fun1();
return 0;
}
编译出错:提示在派生类CSubA、CSubB中均继承了fun1(),子类调用时不知道该如何取舍?
这是由于通过派生时产生多个父类的副本,在调用时产生二义性造成的。只要我们保证在派生时只产生一个父类的副本即可避免这类问题的发生。对派生类CSubA,CSubB修改如下:
Class CSubA:virtual CBase
{
...
}
Class CSubB:virtual CBase
{
...
}
此时即可解决,在子子类中调用父类方法fun1()编译出错的问题。
问题2:当在派生类中重写了基类的方法时,在子子类中调用会出现什么情况呢?
即在CSubA、CSubB中提供对重写基类fun1()的方法,操作如下:
CSubA::fun1()
{
cout<<"CSubA Class..."<<endl;
}
CSubB::fun1()
{
cout<<"CSubB Class..."<<endl;
}
在客户端调用sub.fun1();编译时依旧报错。原因类似,因为父类提供了两个不同的实现,产生了二义性,程序不知该如何取舍?此时应该如何解决呢?
利用强制类型转换。如下:
int main()
{
CSubSubC sub;
((CSubA)sub).fun1();
return 0;
}
此时问题解决,程序正常执行。