虚继承
虚继承
原帖地址:http://blog.myspace.cn/e/400067548.htm
以下都是我个人的理解,估计有问题,看的时候请慎重考虑,仔细判断
1.被虚继承的类就是虚基类2.何为虚继承: 先说普通继承
普通继承: class B: public A,
B从A继承,B会将A做一份copy,作为自身的一部分,然后在加自己独有的一部分。
加入A是一个有虚函数的类,考虑A和B的结构
sizeof(A) = sizeof(A的数据成员) + sizeof(vptr),这个vptr指向A类的 vtable
sizeof(B) = sizof(A的数据成员) + sizeof(B数据成员) + sizeof(vptr),这个vptr指向B类的vtable
虚继承: 虚继承与普通继承不同点在于,子类不实际的copy父类的一部分,而是生成一个引用,指向父类对象
但是在用sizeof统计大小时,依然将父类的成员变量统计在内,此时B的结构如下:
sizeof(B) = sizof(A的数据成员) + sizeof(B数据成员) + sizeof(vptr) + sizeof(pointer to A), vptr指向B类的vtable, 并且多了一个引用指向A对象
虚继承的这个特性在C++的多重继承应用中可以起到很好的作用:
一个没有虚继承的多重继承:
class A
{
void f() ;
};
class B: public A
{
};
class C:public A
{
}
class D: public B, public C
{
}
void main()
{
D d;
d.f();
}
这种情况下编译器会报错:D::f is ambiguous,could be the 'f' in base 'A' of base 'B' of class 'D',or the 'f' in base 'A' of base 'C' of class 'D'
很明显看出:d.f()是有歧义的,因为D中有2个A的copy,也就有2个A::f()函数,编译器不知道应该调用哪一个。
这个问题应用虚继承可以得到很好的解决,类定义重写如下:
class A
{
void f() ;
};
class B: public virtual A
{
};
class C:public virtual A
{
}
class D: public B, public C
{
}
void main()
{
D d;
d.f();
}
此时D中只指向一个A对象,调用d.f(),就是调用那个唯一的A的f()函数,没有歧义,顺利执行。因为此时B和C都是指向同一个A对象。
此时D的结构如下图:
需要注意的是B和C都必须是从A虚继承,只有一个是虚继承仍然会有歧义