在上一篇文章中讨论了C++单一一般继承的对象内存布局http://www.cnblogs.com/uangyy/p/4621561.html

接下来继续讨论第二种情况:

2.单一的虚拟继承:有成员变量,有虚函数和虚函数的覆盖,虚拟继承。

我们假设下面这样一种继承关系

源码如下:

#include <iostream>
using namespace std; class Parent
{
public:
int iparent;
Parent() : iparent() {}
virtual void f()
{
cout << "Parent::f()" << endl;
}
virtual void g()
{
cout << "Parent::g()" << endl;
}
}; class Child : virtual public Parent
{
public:
int ichild;
Child() : ichild() {}
virtual void f()
{
cout << "Child::f()" << endl;
}
virtual void g_child()
{
cout << "Child::g_child()" << endl;
}
};
int main(int argc, char **argv)
{
Child c;
typedef void(*Fun)(void);
Fun pf; cout << "[0] Child::vfptr->" << endl;
cout << " [0] ";
pf = (Fun)*((int *)*(int *)&c + );
pf(); cout << " [0] 0x" << (Fun)*((int *)*(int *)&c + ) << endl; cout << "[1] Child::vbptr->" << endl;
cout << " [0] " << *((int *)*((int *)&c + ) + ) << endl; cout << " [1] " << *((int *)*((int *)&c + ) + ) << endl; cout << " [2] " << *((int *)*((int *)&c + ) + ) << endl; cout << "[2] Child.ichild = " << (int)*((int *)&c + ) << endl; cout << "[3] = 0x" << (int *)*((int *)&c + ) << endl; cout << "[4] Parent::vfptr->" << endl;
cout << " [0] ";
pf = (Fun)*((int *)*((int *)&c + ) + );
pf(); cout << " [1] ";
pf = (Fun)*((int *)*((int *)&c + ) + );
pf(); cout << " [2] 0x" << (Fun)*((int *)*((int *)&c +) + ) << endl; cout << "[5] Parent.iparent = " << (int)*((int *)&c + ) << endl;
return ;
}

代码运行结果如下:

[] Child::vfptr->
[] Child::g_child()
[] 0x00000000
[] Child::vbptr->
[] -
[]
[]
[] Child.ichild =
[] = 0x00000000
[] Parent::vfptr->
[] Child::f()
[] Parent::g()
[] 0x00000000
[] Parent.iparent =

下面是该对象的内存布局图:

由上图我们可以知道:

  1.在虚拟继承关系下,派生类的对象会产生一个名为虚基类表指针的指针vbptr,里面存放的是基类在对象中的偏移地址(从1开始,0单元存放的不知道有什么用)

  2.在这种关系先,被继承的基类放在最后面,首先放的是派生类的成员变量和虚函数表

  3.存放的顺序为:派生类虚函数表指针 -> 虚基类表指针 -> 派生类的成员变量 -> NULL -> 基类虚函数表指针 -> 基类成员变量

sizeof(c) = 24 : 2 * sizeof(vfptr) + 2 * sizeof(int) + sizeof(vbptr) + sizeof(void *)

注意:1.在虚拟机城的继承关系下,派生类的对象会有一个虚基类表指针,占用4个字节;

2.在派生类和被虚拟继承的基类之间有一个空指针。

C++对象内存布局 (二)的更多相关文章

  1. 浅析GCC下C++多重继承 & 虚拟继承的对象内存布局

    继承是C++作为OOD程序设计语言的三大特征(封装,继承,多态)之一,单一非多态继承是比较好理解的,本文主要讲解GCC环境下的多重继承和虚拟继承的对象内存布局. 一.多重继承 先看几个类的定义: 01 ...

  2. JVM-对象及对象内存布局

    目录 前言 类与对象 对象类二分模型 对象 对象内存布局 JOL工具 对象头 Mark Word 类型句柄 对象头与锁膨胀 无锁 偏向锁 轻量级锁 重量级锁 重量级锁降级 实例数据 填充 对象生命周期 ...

  3. JVM 系列(4)一看就懂的对象内存布局

    请点赞关注,你的支持对我意义重大. Hi,我是小彭.本文已收录到 GitHub · AndroidFamily 中.这里有 Android 进阶成长知识体系,有志同道合的朋友,关注公众号 [彭旭锐] ...

  4. 图说C++对象模型:对象内存布局详解

    0.前言 文章较长,而且内容相对来说比较枯燥,希望对C++对象的内存布局.虚表指针.虚基类指针等有深入了解的朋友可以慢慢看. 本文的结论都在VS2013上得到验证.不同的编译器在内存布局的细节上可能有 ...

  5. c++ 对象内存布局详解

    今天看了的,感觉需要了解对象内存的问题.参考:http://blog.jobbole.com/101583/ 1.何为C++对象模型? 引用<深度探索C++对象模型>这本书中的话: 有两个 ...

  6. c++对象内存布局

    这篇文章我要简单地讲解下c++对象的内存布局,虽然已经有很多很好的文章,不过通过实现发现有些地方不同的编译器还是会有差别的,希望和大家交流. 在没有用到虚函数的时候,C++的对象内存布局和c语言的st ...

  7. c++对象内存布局的理解

    我对c++对象内存布局的理解   引言 结合网上的一些资料,通过自己的一番摸索,得出了一点个人见解.现在写下来,希望与各位同学共同探讨,共同进步. 以下所有代码均是在VS2012下测试. 一个普通的基 ...

  8. 好文章系列C/C++——图说C++对象模型:对象内存布局详解

    注:收藏好文章,得出自己的笔记,以查漏补缺!     ------>原文链接:http://blog.jobbole.com/101583/ 前言 本文可加深对C++对象的内存布局.虚表指针.虚 ...

  9. 使用sos查看.NET对象内存布局

    前面我们图解了.NET里各种对象的内存布局,我们再来从调试器和clr源码的角度来看一下对象的内存布局.我写了一个测试程序来加深对.net对象内存布局的了解: using System; using S ...

随机推荐

  1. 【转】Java 集合系列12之 TreeMap详细介绍(源码解析)和使用示例

    概要 这一章,我们对TreeMap进行学习.我们先对TreeMap有个整体认识,然后再学习它的源码,最后再通过实例来学会使用TreeMap.内容包括:第1部分 TreeMap介绍第2部分 TreeMa ...

  2. P3368 【模板】树状数组 2(树状数组维护差分序列)

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...

  3. 如何扒取一个网站的HTML和CSS源码

    一个好的前端开发,当看到一个很炫的页面的时候会本着学习的心态,想知道网站的源码.以下内容只是为了大家更好的学习,拒绝抄袭,支持正版. 1 首先我们要有一个chrome浏览器 2 在本地创建相关文件夹 ...

  4. git——merge和rebase的区别

    参考http://www.jianshu.com/p/129e721adc6e 我在公司里看到其他同事都使用git pull --rebase拉取远程代码,而我总是用git pull,也有同事和我说过 ...

  5. 如何学习Unity3D

      如何学习 第一步首先了解unity3d的菜单,视图界面.这些事最基本的基础,可以像学word操作一样,大致能明白有几个菜单,几个基本的视图,各自起什么作用的就可以了. 第二步理解场景里面的坐标系统 ...

  6. String数据类型转换

    String是final类,提供字符串不可修改.强制类型转换,String类型无处不在.下面介绍一些常见的String数据类型转换. String数据类型转换成long.int.double.floa ...

  7. jboss-eap-6.2修改端口号

    最近要改版一个项目,用来配合日常工作使用,需要在服务器上放多个jboss,那么就需要修改jboss的端口,如果服务器上配置了JBOSS_HOME,需要先删除,否则配置修改不会生效,会依然用老的jbos ...

  8. mstsc windows7/10远程桌面身份验证错误 要求的函数不受支持

    之前好好的能远程桌面连接到服务器,但是今天来就不能连接上了,并提示:身份验证错误.要求的函数不受支持. 猜想可能是Windows又更新了什么鬼,后面查询资料知道是由于CredSSP加密Oracle修正 ...

  9. Java中Math对象的属性与方法

    Math.sqrt() ——————>计算平方根Math.cbrt()————————>计算立方根Math.pow(a, b)——————————>计算a的b次方Math.max( ...

  10. PAT_A1003#Emergency

    Source: PAT A1003 Emergency (25 分) Description: As an emergency rescue team leader of a city, you ar ...