C++对象内存布局 (二)
在上一篇文章中讨论了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++对象内存布局 (二)的更多相关文章
- 浅析GCC下C++多重继承 & 虚拟继承的对象内存布局
继承是C++作为OOD程序设计语言的三大特征(封装,继承,多态)之一,单一非多态继承是比较好理解的,本文主要讲解GCC环境下的多重继承和虚拟继承的对象内存布局. 一.多重继承 先看几个类的定义: 01 ...
- JVM-对象及对象内存布局
目录 前言 类与对象 对象类二分模型 对象 对象内存布局 JOL工具 对象头 Mark Word 类型句柄 对象头与锁膨胀 无锁 偏向锁 轻量级锁 重量级锁 重量级锁降级 实例数据 填充 对象生命周期 ...
- JVM 系列(4)一看就懂的对象内存布局
请点赞关注,你的支持对我意义重大. Hi,我是小彭.本文已收录到 GitHub · AndroidFamily 中.这里有 Android 进阶成长知识体系,有志同道合的朋友,关注公众号 [彭旭锐] ...
- 图说C++对象模型:对象内存布局详解
0.前言 文章较长,而且内容相对来说比较枯燥,希望对C++对象的内存布局.虚表指针.虚基类指针等有深入了解的朋友可以慢慢看. 本文的结论都在VS2013上得到验证.不同的编译器在内存布局的细节上可能有 ...
- c++ 对象内存布局详解
今天看了的,感觉需要了解对象内存的问题.参考:http://blog.jobbole.com/101583/ 1.何为C++对象模型? 引用<深度探索C++对象模型>这本书中的话: 有两个 ...
- c++对象内存布局
这篇文章我要简单地讲解下c++对象的内存布局,虽然已经有很多很好的文章,不过通过实现发现有些地方不同的编译器还是会有差别的,希望和大家交流. 在没有用到虚函数的时候,C++的对象内存布局和c语言的st ...
- c++对象内存布局的理解
我对c++对象内存布局的理解 引言 结合网上的一些资料,通过自己的一番摸索,得出了一点个人见解.现在写下来,希望与各位同学共同探讨,共同进步. 以下所有代码均是在VS2012下测试. 一个普通的基 ...
- 好文章系列C/C++——图说C++对象模型:对象内存布局详解
注:收藏好文章,得出自己的笔记,以查漏补缺! ------>原文链接:http://blog.jobbole.com/101583/ 前言 本文可加深对C++对象的内存布局.虚表指针.虚 ...
- 使用sos查看.NET对象内存布局
前面我们图解了.NET里各种对象的内存布局,我们再来从调试器和clr源码的角度来看一下对象的内存布局.我写了一个测试程序来加深对.net对象内存布局的了解: using System; using S ...
随机推荐
- 最容易理解的CSS的position教程——十步图解CSS的position
CSS的positon,我想做为一个Web制作者来说都有碰到过,但至于对其是否真正的了解呢?那我就不也说了,至少我自己并不非常的了解其内核的运行.今天在Learn CSS Positioning in ...
- Java 6中类路径ClassPath对通配符的支持
在java 6之前,如果我们的应用依赖多个jar包,通常是将所有jar包文件枚举设置到环境变量CLASSPATH或者命令行参数-classpath(-cp)中.通常我们需要写一段shell脚本实现该功 ...
- 控制台——EventLog实现事件日志操作
我们应该如何通过写代码的方式向其中添加“日志”呢? 在操作之前,先明确几个概念: 1:事件日志名(logName):“事件查看器”中的每一项,如“应用程序”.“Internet Explorer”.“ ...
- Node.js概述
Node.js最重要的特性:通过单线程实现异步处理环境 Node.js解决的问题: Node.js修改了客户端连接服务器端的连接方法,不需要为每个客户端连接创建一个新的线程,而是为每个客户端连接触发一 ...
- Django 更新字段
Django在1.7以后的版本提供数据迁移命令,用来在修改模型中的字段,更新到数据库 1. python manager.py makemigrations 命令用来创建迁移文件版本的 2. pyth ...
- C#斐波那契数列方法
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- vue编辑回显问题
真是疯了,vue怪毛病真多 就下面这玩意儿,多选组合框,新增的时候好用的不行不行的,到了编辑的时候,要回显数据,怪毛病一堆一堆的 首先,回显的时候要传一个数组,但是这个数组里的元素得是字符串类型的,如 ...
- __declspec(dllexport)
__declspec(dllexport) (2010-06-17 10:04:28) 转载▼ 标签: __declspec dllexport 导出 it 分类: C 先看代码:以下是在dev-c+ ...
- Js—innerHTML和innerText的区别
1.innerHTML属性和innerText属性 都是对元素的一个操作,简单讲,innerHTML可以在某种特定环境下重构某个元素节点的DOM结构,innerText只能修改文本值 在JavaScr ...
- H5 应用程序缓存(离线缓存)
离线缓存这个功能的实现有以下步骤: 1,以nginx做web服务器为例,在mime.types文件中添加一行:text/cache-manifest manifest,作用是为了让服务器识别该 ...