C++对象模型(11)-- 虚基类

1、虚基类的引入

我们再来复习一下“多重继承的对象布局”,假设继承的类结构是这样的:

相应的代码:

class W {
public:
    int i_w;
};
class X : public W {};
class Y : public W {};
class Z : public X, public Y {};

我们在main()函数中加入如下代码:

Z z;
cout << z.i_w << endl; //这句话编译会报错

系统提示i_w的访问不明确。为什么呢?

因为定义Z对象时,W类会被继承2次,1次是Z --> X --> W,1次是Z --> Y --> W。虚基类的提出就是为了解决这种重复继承的问题,让W类只被继承1次。

虚基类的代码如下:

class W {
public:
    int i_w;
};
class X : virtual public W {};
class Y : virtual public W {};
class Z : public X, public Y {};

2、虚基类表、虚基类表指针

我们把前面虚基类的代码修改一下:

using namespace std;

class W {
public:

};
class X : virtual public W {};
class Y : virtual public W {};
class Z : public X, public Y {};

int main()
{
    cout << sizeof(W) << endl;
    cout << sizeof(X) << endl;
    cout << sizeof(Y) << endl;
    cout << sizeof(Z) << endl;
}

输出如下:

为什么输出的结果是:1、4、4、8呢?

这里要引入2个概念:1、虚基类表 vbtable 2、虚基类表指针 vbptr。

虚基类表指针占4个字节,类X、Y各含1个虚基类表指针,类Z继承这2个虚基类表指针,所以Z对象占8个字节。

3、虚基类中的对象数据布局

为了更好地观察虚基类中的对象数据布局,我们往每个类中都增加1个成员变量。

class W {
public:
    int i_w;
};
class X : virtual public W {
public:
    int i_x;
};
class Y : virtual public W {
public:
    int i_y;
};
class Z : public X, public Y {
public:
    int i_z;
};

(1) cl /d1 reportSingleClassLayoutX ch08.cpp

虚基类表指针占4个字节,i_x占4个字节,i_w占4个字节,所以类X的对象占12个字节。

类X对象数据布局:

(2) cl /d1 reportSingleClassLayoutY ch08.cpp

类Y对象的数据布局跟类X对象类似。

(3) cl /d1 reportSingleClassLayoutZ ch08.cpp

类Z对象数据布局:

4、虚基类带虚函数时的对象布局

4.1 类W有虚函数(其他类都没虚函数)

virtual void w_h() { cout << "W::w_h()" << endl; }

这时类X的对象成员布局是这样的:

类Z的对象成员布局是这样的:

从图中可以看到,这个时候虚函数表指针vptr在子对象w的头部。

4.2 类X有虚函数(类W、X都有虚函数)

virtual void x_h() { cout << "X::x_h()" << endl; }

这时类X的对象成员布局是这样的:

类Z的对象成员布局是这样的:

4.3 类Z有虚函数 (类W、X也有虚函数)

virtual void z_h() { cout << "Z::z_h()" << endl; }

这时的对象成员布局和4.2中一样:对象Z和X共用同一个虚函数表指针。

4.4 类Z有虚函数(其他类都没虚函数)

此时Z类对象的对象布局如下:

从上面的结果看,虚基类的对象布局有如下规律:

(1)在孙子类Z的对象布局中,爷爷类(W类)的数据总是位于最后位置。

(2)父类X、Y都有一个虚基类表指针。

(3)仅爷爷类W有虚函数时,它的虚函数表指针在W类对象的头部。

(4)仅X或Y类有虚函数时,虚函数表指针就在X或W类对象的头部;在Z类对象中,虚函数表指针也位于对象的头部。

比如当Y有虚函数,其他类都没有虚函数时,类Z对象的对象布局如下:

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值