博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++内存布局之虚拟继承
阅读量:6316 次
发布时间:2019-06-22

本文共 2645 字,大约阅读时间需要 8 分钟。

虚拟继承

即派生类继承多次基类,但在派生类中只存在一份基类的拷贝。编译器实现虚拟继承的方式并不相同,下面我结合VS2010来探讨C++虚拟继承。声明一个虚基类CommonBase,两个从虚基类虚拟派生Base1和Base2,然后D,公有多继承自Base1和Base2,具体类定义如下:

class CommonBase{public:    virtual void commonBaseFunc() = 0;private:    int commonBase_data;};class Base1 : public virtual CommonBase{public:    virtual void Base1_Fun1(){}    virtual void Base1_Fun2(){}    virtual void commonBaseFunc(){}private:    int Base1_data;};class Base2 : public virtual CommonBase{public:    virtual void Base2_Fun1(){}    virtual void Base2_Fun2(){}private:    int Base2_data;};class Derived : public Base1, public Base2{public:    virtual void Base1_Fun1(){}    virtual void Base2_Fun2(){}private:    int Derived_data;};

现在我们来看看Derived类对象的内存布局,编译之后,我们在生成窗口看到如下信息:

1>  class Derived    size(36):1>      +---1>      | +--- (base class Base1)1>   0    | | {vfptr}1>   4    | | {vbptr}1>   8    | | Base1_data1>      | +---1>      | +--- (base class Base2)1>  12    | | {vfptr}1>  16    | | {vbptr}1>  20    | | Base2_data1>      | +---1>  24    | Derived_data1>      +---1>      +--- (virtual base CommonBase)1>  28    | {vfptr}1>  32    | commonBase_data1>      +---1>  1>  Derived::$vftable@Base1@:1>      | &Derived_meta1>      |  01>   0    | &Derived::Base1_Fun11>   1    | &Base1::Base1_Fun21>  1>  Derived::$vftable@Base2@:1>      | -121>   0    | &Base2::Base2_Fun11>   1    | &Derived::Base2_Fun21>  1>  Derived::$vbtable@Base1@:1>   0    | -41>   1    | 24 (Derivedd(Base1+4)CommonBase)1>  1>  Derived::$vbtable@Base2@:1>   0    | -41>   1    | 12 (Derivedd(Base2+4)CommonBase)1>  1>  Derived::$vftable@CommonBase@:1>      | -281>   0    | &thunk: this-=16; goto Base1::commonBaseFunc1>  1>  Derived::Base1_Fun1 this adjustor: 01>  Derived::Base2_Fun2 this adjustor: 121>  1>  vbi:       class  offset o.vbptr  o.vbte fVtorDisp1>        CommonBase      28       4       4 0

    从输出的信息来看,虚拟继承有别于非虚拟继承的一个区别就是把虚基类放在整个类对象的末尾,而非虚拟继承则是按照继承的顺序先存放父类,再到子类。下面我们就来说说这些信息究竟表示什么含义。

    对于size(36)就指明Derived对象的大小为36个字节,我们看看Base2的vftable,其中-12表示Base2在Derived类中的偏移量。Base1的vbtable中-4表示Base1的vbtable与Base1这个对象的偏移量,因为一般都是把vftable放在对象的前面,所以vbtable与对象首地址的偏移量一般就是中间隔着vftable,24表示Base1的vbtable与虚基类CommonBase首地址的偏移量,从上图可以看出Base1的vbtable与Derived的偏移量为4,CommonBase与Derived的偏移量为28,这24加上4就刚好等于28,同理,Base2也一样。

    我们着重来看一下,CommonBase的vftable,-28就不用多说了,表示CommonBase相对于Derived首地址的偏移量,重点是这句&thunk: this-=16;goto Base1::commonBaseFunc,这句就说明VS2010使用了thunk技术来实现虚拟继承的时候,虚基类CommonBase只存在一份拷贝

在Derived,由于Base1已经重写了CommonBase的虚函数commonBaseFunc(),所以当Derived调用commonBaseFunc()函数时才会跳转到

Base1去执行。

    Derived::Base2_Fun2 this adjustor:12表示当一个Derived对象d调用Base2的Base2_Fun2()函数时,this指针需要跳转的偏移量,从图上可以看出12就是Base2相对于Derived首地址的偏移量。

转载地址:http://uscaa.baihongyu.com/

你可能感兴趣的文章
异步编程的世界
查看>>
最近话题火爆的四件事你知道不?
查看>>
SpringBoot整合MyBatis
查看>>
Android 类库书签更新(一)
查看>>
Unity3D Input按键系统
查看>>
简单的一条SQL,不简单的做事思维 NOT IN 、NOT EXISTS、LEFT JOIN用法差别 ...
查看>>
DataWorks:任务未运行自助排查
查看>>
ionic/cordova热部署
查看>>
「镁客早报」特斯拉裁员,马斯克解释没有办法;微软推出Azure DevOps赏金计划...
查看>>
centos 7.4 使用 pgxc_ctl 安装与使用
查看>>
Redis 单key值过大 优化方式
查看>>
【数据库】表分区
查看>>
nutz-sqltpl 1.3.4.RELEASE 发布,在 Nutz 项目中“解决 Java 拼接 SQL”问题
查看>>
城市 | 800个地铁站数据透析的京沪白领图鉴:隐形土豪、无产中产阶级和猪猪女孩...
查看>>
前端脚本!网站图片素材中文转英文
查看>>
linux的常用易忘命令
查看>>
PHP 分割字符串
查看>>
java 基于QRCode、zxing 的二维码生成与解析
查看>>
关于职业规划的一些思考
查看>>
img垂直水平居中与div
查看>>