学过C++的人都知道,里面有个虚拟继承是为了使得类多重继承方式下成员名称二义性的问题的。
假如我们定义一个普通类A,然后定义两个普通类B,C都来继承A,最后我们定义一个普通类D类多重继承B和C,那么现在我们每一个D的实例对象中都有两份A的数据和方法。
所以我们如果使用基类A中某个方法时就会产生二义性的问题。
故而,虚拟继承应运而生,有了虚拟继承,每构造基类时就会检查该类是否已经存在了。故而能用虚拟继承的方式来避免上面所说的问题。
然而,我在书上看到这个地方的时候,我又产生了疑问:
众所周知,我们在普通继承时,B和C中分别有A的一份拷贝。但虚拟继承时,整个派生类D中只有一个基类A,那么它的那份拷贝应该放在什么地方呢?
猜想一:独立的放在类D中独立的一块区域,无法用即无法用B::fA()访问,也无法用C::fA()访问。
猜想二:放在第一个引用它的基类中,(在这里便是放在B类中一份拷贝)即,可以用B::fA()访问,但不可以用C::fA() 来访问。
猜想三:放在第一个引用它的基类中,但是第二个引用它的基类有它的一个类似指针功能的东西能说明基类在什么地方,即我们既可以用B::fA()也可以用C::fA()来访问。
自己编写了如下代码,以作验证:
#include <iostream>
using namespace std;
class A
{
public:
void fA() { cout <<"fA()"<<endl; }
};
class B: virtual public A
{};
class C: virtual public A
{};
class D: public B, public C
{};
int main()
{
D d;
d.fA();
d.B::fA();
d.C::fA();
return 0;
}
运行结果:
fA()
fA()
fA()
Process returned 0 (0x0) execution time : 0.011 s
Press any key to continue.
上面的结果明确的说明了,猜想一和猜想二是错误的,至于猜想三是否正确,现在还不能下结论。
这里介绍一篇文章:http://www.cppblog.com/chemz/archive/2007/06/12/26135.html
看了以后,你会发现猜想三也是错误的,正确的是,类D中有个虚基类表来描述类间的虚继承关系。
再高深的东西,我也说不上了,推荐一篇白杨的《RTTI、虚函数和虚基类的开销分析及使用指导》。
有兴趣的可以看看。