博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
对象内存布局 (12)
阅读量:5869 次
发布时间:2019-06-19

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

下面来看看虚基类对对象内存布局的影响。虚基类的主要作用就是在所有的派生类中,保留且仅保留一份虚基类的suboject。

 

a. 一个虚基类的情况

#include 
using namespace std;class Base{public: int base_member;};class Derived : public virtual Base {};int main(void){ Base b; Derived d; cout << sizeof(b) << endl; cout << sizeof(d) << endl; return 0;}

运行结果:

注意使用了虚继承,即class Derived : public virtual Base。这次Derived的对象大小为什么为8 bytes呢?这是因为编译器会给Derived对象安插一个虚基类表指针vbptr,下面给出Derived对象的memory layout:

 

 

虚基类表指针vbptr指向Derived类的virtual bass class table(虚基类表),虚基类表中存放的是Derived类的虚基类表指针到虚基类实例指针的偏移量

 在main函数的return前,增加如下语句:

#include 
using namespace std;class Base{public: int base_member;};class Derived : public virtual Base {};int main(void){ Base b; Derived d; cout << sizeof(b) << endl; cout << sizeof(d) << endl; cout << "Derived object d's vbptr = " << (unsigned long*)(&d) << endl; cout << "Address of virtual base class table = " << (unsigned long*)*(unsigned long*)(&d) << endl; cout << "Item 1 in virtual base class table = " << *(unsigned long*)*(unsigned long*)(&d) << endl; cout << "Item 2 in virtual base class table = " << *((unsigned long*)*(unsigned long*)(&d) + 1) << endl; cout << "Item 3 in virtual base class table = " << *((unsigned long*)*(unsigned long*)(&d) + 2) << endl; cout << "The address of virtual base class Base = " << (Base*)(&d) << endl; return 0;}

编译后运行结果:

编译后运行结果:

不难发现,虚基类示例地址 = vbptr + offset,即0x0012FF78 = 0x0012FF74 + 4。图示如下:

b. 我们来看看Derived有两个虚基类的情况:

#include 
using namespace std;class Base1{public: int base1_member;};class Base2{public: int base2_member;};class Derived : public virtual Base1, public virtual Base2 {};int main(void){ Base1 b1; Base2 b2; Derived d; cout << sizeof(b1) << endl; cout << sizeof(b2) << endl; cout << sizeof(d) << endl; cout << "Derived object d's vbptr = " << (unsigned long*)(&d) << endl; cout << "Address of virtual base class table = " << (unsigned long*)*(unsigned long*)(&d) << endl; cout << "Item 1 in virtual base class table = " << *((unsigned long*)*(unsigned long*)(&d) + 0) << endl; cout << "Item 2 in virtual base class table = " << *((unsigned long*)*(unsigned long*)(&d) + 1) << endl; cout << "Item 3 in virtual base class table = " << *((unsigned long*)*(unsigned long*)(&d) + 2) << endl; cout << "Item 3 in virtual base class table = " << *((unsigned long*)*(unsigned long*)(&d) + 3) << endl; cout << "The address of virtual base class: Base1's instance = " << (Base1*)(&d) << endl; cout << "The address of virtual base class: Base2's instance = " << (Base2*)(&d) << endl; return 0;}

编译运行结果如下:

 

Derived对象的memory layout图解如下:

 

 

不管Derived类有多少个虚基类,它只有一个vbptr和一个virtual base class table

你可能感兴趣的文章
可给pdf批量添加书签的神器
查看>>
linux下nginx+python+fastcgi部署总结(django版)
查看>>
idea常用设置
查看>>
【那些拍案叫绝的好代码-一行代码的事】js中有关数组的去重
查看>>
如何让语音交互更流畅?
查看>>
[Git]-命令基操
查看>>
spring常见问题总结
查看>>
Linux系统安装配置proftp服务器
查看>>
Angular JS 模块
查看>>
关于extjs的tabpanel加载tab项并且tab项以iframe显示时的页面刷新问题
查看>>
使用Java创建rest 服务 通过HTTP请求访问资源
查看>>
java.util.concurrent.CountDownLatch组件说明
查看>>
jQuery UI 自动完成(Autocomplete)
查看>>
CCImage.mm
查看>>
html中的click事件被触发两次如何解决
查看>>
驰骋工作流引擎表单设计器--表单装载前数据填充
查看>>
微信分享链接或网站文章到微信朋友圈,缩略图片不显示,该如何解决?
查看>>
无屏无外设操作,SSH,VNC
查看>>
企业官网图片与腾讯云服务器映射
查看>>
5分钟制作欢乐捕鱼app
查看>>