对于普通的C++对象内存布局,简单得不得了,就不做总结了。这里只总结涉及到虚拟继承的情况。
因为不同编译器对虚拟继承的实现采用不同的方式,所以要完整的分析是不可能的。这里只考虑VS2005/2008,还有简单涉及GCC编译器。
1、
单个虚拟继承
只是为了分析而已,实际中并没有太大的作用。跟虚拟继承相关的派生类对象的内存布局跟具体的编译器相关。
(1)VS编译器:无论有无虚函数,必然含有虚基类表指针。虚基类表中的内容为本类实例的偏移和基类实例的相对偏移值。如果有虚函数,那么基类的虚函数表跟派生类的虚函数表是分开的。
在内存布局上,地址从低到高,顺序如下:派生类的虚函数表指针+虚基类表指针+派生类的成员变量+“间隔”(4个字节)+基类的虚函数表指针+基类的成员变量。派生类跟基类实例的位置关系跟普通继承正好相反。
说明:“间隔”产生的原因是派生类重写了基类的虚函数。如果没重写,则这一项没有。
图 1 VS编译器—单个虚拟继承
(2)GNU的GCC编译器:跟VS的编译器类似,有不同的地方是,虚基类表跟派生类的虚函数表合并。另外通过虚基类表指针往正负两个方向寻址,可以获得
不同偏移值,也就是说有两个功能一样的虚函数表。不过在实际应用的时候,不知道虚基类表是否真的有用,测试了简单的情况发现编译器做了优化,根本就没有用
虚基类表来寻址虚基类实例。
图 2 GCC编译器—单个虚拟继承
2、
虚拟继承多个基类
虚基类表要增加内容,有N个虚基类就有N项基类实例偏移值,再加上1项本类实例的偏移值,也就是N+1。
假设C虚拟继承了A类和B类,考虑最复杂的情况(都有虚函数),那么C类对象的内存布局如下
(VS编译器):
C类虚函数表指针+虚基类表指针+C类成员变量+A类间隔(4个字节) + A类虚函数表指针+ A类成员变量+ B类间隔(4个字节)+B类虚函数表指针+ B类成员变量。
说明:当派生类重写了该基类的虚函数,才会有“间隔”。“间隔”属于虚函数被重新实现了的虚基类,可能是一个标志,也有可能是在函数调用的时候用上。不是很清楚。
图 3 VS编译器—虚拟继承多个基类
(GCC编译器):
C类虚函数表指针(包含虚基类表) + C类成员变量 + A类虚函数表指针 + A类成员变量 + B类虚函数表指针 + B类成员变量。
相比较执行,使用GCC编译器,派生类对象小一些。(图略)
3、
虚拟继承之菱形继承
这里的菱形继承指的是:B、C虚拟继承A,然后D普通继承B、C。
D类的对象的内存布局如下
(VS编译器)
B类虚函数表指针(该虚函数表包含D类独有的虚函数的地址)+B类虚基类表指针+B类成员变量+C类虚函数表指针+C类虚基类表指针+C类成员变量+D类成员变量+“间隔”+A类虚函数表指针+A类成员变量。
说明:如果A类的虚函数没有被重写,那么就没有“间隔”。
图 4 VS编译器—菱形继承
(GCC编译器)
把B、C类的虚函数表跟虚基类表合并就是了。(图略)
4
、VS编译器,“间隔”的疑问
“间隔”的问题,在没有虚函数的情况下,重写是没有“间隔”的,所以觉得可能跟虚函数有关,也就是说是为了实现多态,
具体是用在哪个地方,做了简单的反汇编调试(父类指针指向子类对象,调用被子类重写了的虚函数),并没有发现哪里用到了“间隔”,可能要在复杂的调用才会
用上吧,目前搞不清楚。
5
、虚基类表的问题
通过反汇编调试发现在使用多态的时候,VS编译器会去使用虚基类表,用于寻址虚基类地址。而GCC编译器则没有这么做,测试了比较简单的情况,发现它做了优化,并没有利用虚基类表,而是直接在派生类对象地址上加上一个常数,获得虚基类实例的地址。
分享到:
相关推荐
总结,通过结合Qt的图形界面和绘图能力,以及Zint的强大条形码生成功能,我们可以轻松地在Windows环境下(如VS2010+Qt5.4.0+Win7)实现条形码打印。关键在于理解各个组件的用途,以及如何在它们之间建立有效的接口和...
总结,Vc++贸易公司信息管理系统(SQL)是一个集成了C++编程技术和SQL数据库管理的综合应用,它展示了两者在企业级应用中的强大能力。通过深入理解并掌握这些技术,开发者能构建出更高效、更安全的信息管理系统,...
6. **更好的Android测试工具**:集成的测试工具如AndroidJUnit5和Espresso,使得单元测试和UI测试更加便捷,确保应用的稳定性和可靠性。 三、安装与设置 下载的压缩包"android-studio-ide-4.2.2.7z"包含了完整的...
6. **运行与测试**:在主程序中创建`CustomDialogEx`的实例并显示,然后通过实际操作来测试对话框的功能和交互性。 "QtCustomDialogEx"的压缩包可能包含了以上步骤的所有源码,包括.pro项目文件、.h头文件、.cpp源...
总结,"qthtml5.9英文文档.7z" 提供了关于Qt5 HTML5的详尽资料,涵盖了从基本概念到高级特性的各个方面,对于想要在Qt环境中利用HTML5技术开发应用的开发者来说是一份宝贵的资源。通过深入学习和实践,开发者可以...
总结,"1990-2019年历年真题.7z"是软件设计师备考的宝贵资源,通过它,考生可以全方位地复习和提升,确保在考试中取得理想的成绩。无论你是初学者还是有经验的开发者,都应该充分利用这些材料,以达到最佳的备考效果...
在本文中,我们将深入探讨如何使用Microsoft Foundation Class (MFC) 库来开发一个静态分割视图的Single Document Interface (SDI) 应用程序,这个主题与提供的压缩包文件"**MFCSpiltSDI分割视图.7z**"紧密相关。...
5. **布局编辑器**:视觉化的布局编辑器允许开发者实时预览界面设计,同时支持拖放组件,方便界面构建。 6. **版本控制集成**:与Git和其他版本控制系统无缝集成,便于团队协作和版本管理。 二、安装与使用 安装...
然后,我们设置渲染状态,比如启用深度测试(Depth Buffer),禁用背面剔除(Culling),并选择适当的填充模式(Fill Mode): ```cpp device->SetRenderState(D3DRS_ZENABLE, TRUE); device->SetRenderState(D3DRS...
在cocos2d-x中,开发者可以利用可视化编辑器(如Cocos Studio)进行界面布局,编写C++或Lua脚本实现逻辑,使用Tiled地图编辑器创建关卡,通过Audio Manager处理音效,最后打包并发布到目标平台。 4. **示例项目分析...
根据给定文件的信息,我们可以总结出以下相关的IT知识点: ### 1. Java基本类型与类实例判断 **知识点概述:** - **基本类型与对象类型的区别:** 在Java中,`Integer`是一个包装类,而`int`是基本类型。 - **`...
3. **PCB设计**:印刷电路板设计文件包含了电路的布局和布线,确保所有电子元件在物理空间上的正确放置和电气连接。良好的PCB设计可以优化信号完整性,降低电磁干扰,并提高系统的可靠性。 4. **源代码**:这部分...
Go语言的内存布局涉及到堆和栈的概念,了解内存布局对于理解Go语言如何管理内存是非常有帮助的。 ##### 2. 指针陷阱 指针陷阱是指由于不当使用指针导致的问题,如空指针解引用、悬垂指针等。 ##### 3. cgo cgo是...
总结来说,这个项目展示了如何利用MFC进行GUI编程,通过用户交互控制三维对象的视觉效果。它涵盖了MFC控件的使用、消息处理机制、以及可能的三维图形渲染技术。通过学习和分析这个项目,开发者可以深化对MFC和图形...
根据提供的文档内容,我们可以总结和扩展出以下几个关键的IT知识点: ### 1. ASCII码值的理解 - **问题描述**:题目询问了四个字符(A、a、Z、X)中ASCII码值最小的一个。 - **知识点解析**: - ASCII码是一种用于...
- **播放器界面设计**:主界面布局简洁明了,包含播放列表、播放控制按钮(播放、暂停、停止、上一首/下一首)、进度条等元素。 - **按钮上的位图显示**:为每个控制按钮添加图标,提升用户体验。 ##### 3.2 各模块...
根据提供的文件信息,我们可以分析并总结出关于TSP问题(货郎担问题)的相关知识点。 ### TSP问题(货郎担问题) #### 1. 定义与背景 TSP问题,即Traveling Salesman Problem(旅行商问题),是组合优化问题中的...
- MATLAB的特点和优势:MATLAB的命令与数学表达式相似,使得编程更为直观,同时支持与其他编程语言的集成,如C、FORTRAN、C++、JAVA。 2. **第二章 信号产生及其MATLAB实现** - 离散信号:MATLAB可以方便地生成...
在实际开发过程中,这类文件可能包括原理图、PCB布局文件、代码仓库、硬件测试报告、用户手册等。 总结以上,这个项目涉及物联网技术在智能家居中的应用,特别是自动房间照明系统的开发。它涵盖了硬件设计(PCB)、...
根据给定文件的信息,我们可以总结出以下几个重要的知识点: ### 1. Windows 98 资源管理器的文件删除机制 **知识点说明**:在Windows 98系统中,当用户选择删除一个子目录或者一组子目录时,该操作不仅会删除所选...