为什么要引入虚拟继承
虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如:类D继承自类B1、B2,而类B1、B2都继承自类A,因此在类D中两次出现类A中的变量和函数。这样一个类D的对象在访问继承的类A中的成员时就会出现二义性问题。如下面程序:
#include <iostream>
using namespace std;
class A
{
protected:
int a;
public:
A(int m=1)
{
a = m;
cout << "class A " << a << endl;
}
};
class B:public A
{
public:
B(int m=2):A(m)
{
cout << "class B " << a << endl;
}
};
class C:public A
{
public:
C(int m=3):A(m)
{
cout << "class C " << a << endl;
}
};
class D:public B, public C
{
public:
D(int m = 100):B(m)
{
cout << "class D " << a << endl;
cout << "class D " << a << endl;
}
};
int main()
{
D d;
}
编译时报错43: error: reference to ‘a’ is ambiguous。这是因为所有A的成员在D中都是成对出现的。这时就需要用到虚继承来解决这种二义性。将B、C对A的继承定义为虚拟继承就可以了。
通过下面四种情况来说明虚继承与非虚继承的区别:
第一种情况:
class a
{
virtual void func();
}
class b:public virtual a
{
virtual void foo();
}
第二种情况 :
class a
{
virtual void func();
}
class b:public a
{
virtual void foo();
}
第三种情况 :
class a
{
virtual void func();
char x;
}
class b:public virtual a
{
virtual void foo();
}
第四种情况:
class a
{
virtual void func();
char x;
}
class b:public a
{
virtual void foo();
}
如果对这四种情况分别求sizeof(a),sizeof(b)。结果是什么样的呢?下面是输出结果:(在vc6.0中运行)
第一种:4,12
第二种:4,4
第三种:8,16
第四种:8,8
注:上述各类中的各成员在内存中排列顺序未必为图中所示。
例二
#include <iostream>
using namespace std;
class B
{
public:
int i;
virtual void vB(){cout<<"B::vB"<<endl;}
void fB(){cout<<"B::fB"<<endl;}
};
class D1 : virtual public B
{
public:
int x;
virtual void vD1(){cout<<"D1::vD1"<<endl; }
void fD1(){cout<<"D1::fD1"<<endl;}
};
class D2 : virtual public B
{
public:
int y;
void vB(){cout<<"D2::vB"<<endl;}
virtual void vD2(){cout<<"D2::vD2"<<endl;}
void fD2(){cout<<"D2::fD2"<<endl;}
};
class GD : public D1,public D2
{
public:
int a;
void vB(){cout<<"GD::vB"<<endl;}
void vD1(){cout<<"GD::vD1"<<endl;}
virtual void vGD(){cout<<"GD::vGD"<<endl;}
void fGD(){cout<<"GD::fGD"<<endl;}
};
2)类图:
3)内存结构:
基类B:
vfptrB (指向B::fB(),B::vB()) |
int i |
类D1虚继承B:
vfptrD1 (指向D1::fD1(), D1::vD1()) |
vbptrD1 |
int x |
vfptrB (指向B::fB(),B::vB()) |
int i |
类D2虚继承B:
vfptrD2 (指向D2::fB(), D2::fD2(), D2::vD2()) |
vbptrD2 |
int y |
vfptrB (指向B::fB(),B::vB()) |
int i |
类GD多重继承D1,D2(不是虚继承):
vfptrD1 (指向D1::fD1(), GD::vD1(),GD::fGD(), GD::vGD()) |
vbptrD1 |
int x |
vfptrD2 (指向GD::fB(), D2::fD2(), D2::vD2()) |
vbptrD2 |
int y |
vfptrB (指向GD::fB(),B::vB()) |
int i |
Int a |
所以sizeof(GD)=9*4=36个字节。