关于C++多重继承下虚表结构的问题

前言

昨天写一个项目时遇到一个很诡异的现象 如下代码所示:

class ParentA {
public :
	int a=0x123456;
	virtual void vFunParentA(){
		std::cout << "vFunParentA" << std::endl;
	}
};
class ParentB {
public:
	int b = 0x456;
	virtual void vFunParentB() {
		std::cout<<"vFunParentB"<<std::endl;
		int i = 0;
	}
};
class Child:public ParentA,public ParentB {
	int c = 0x789;
};
int main()
{

	//注意这里使用void*
	void* pChild = new Child;
	//强转
	ParentB* pParentB = (ParentB*)pChild;
	//强转
	ParentA* pParentA = (ParentA*)pChild;

	pParentB->vFunParentB();
	pParentA->vFunParentA();

	getchar();

}

现在执行后我们的预期输出为

vFunParentB
vFunParentA

但实际输出:

vFunParentA
vFunParentA

当时百思不得其“姐”,最后发现是自己对多重继承下的虚表内存结构不够了解。

博主另一外一篇关于虚表的:
c-15 c++虚表

在多重继承下Child内存结构应该是如下结构:

由于我们使用 void * 类型强转为ParentBParentA返回的指针地址依然是ParentA,而没有做内存偏移计算.如下图所示:

当我们不适用void*强转后编译器会帮我进行偏移计算会迫使ParentB偏移8字节,从而使pParentB 指向正确的内存虚表。

在单一继承下不会出现这类问题,我们最后看下本例中的内存结构:




到此这篇关于关于C++ 多重继承下虚表结构的问题的文章就介绍到这了,更多相关C++ 多重继承虚表内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • c++ 虚函数,虚表相关总结

    面向对象,从单一的类开始说起. class A { private:     int m_a;     int m_b; }; 这个类中有两个成员变量,都是int类型,所以这个类在内存中占用多大的内存空间呢? sizeof(A), 8个字节,一个int占用四个字节.下图验证: 这两个数据在内存中是怎样排列的呢? 原来是这样,我们根据debug出来的地址画出a对象在内存的结构图 如果 class A 中包含成员函数呢? A 的大小又是多少? class A { public:     void f

  • 探究c++虚表实现代码

    本文简单探究虚表实现. 如下代码中有一个基类CPerson和子类CStudent:public.并有两个虚函数run和cry. #include<iostream> using namespace std; class CPerson { public: virtual void run() { cout << "Person is runing. \r\n"; } virtual void cry() { cout << "Person

  • 关于C++多重继承下虚表结构的问题

    前言 昨天写一个项目时遇到一个很诡异的现象 如下代码所示: class ParentA { public : int a=0x123456; virtual void vFunParentA(){ std::cout << "vFunParentA" << std::endl; } }; class ParentB { public: int b = 0x456; virtual void vFunParentB() { std::cout<<&qu

  • Java实现级联下拉结构的示例代码

    目录 前言 构建统一返回下拉结构 构建集合<对象>转下拉树工具类 构建List<Map>转下拉或下拉树的工具类 前言 在开发过程中,会遇到很多的实体需要将查出的数据处理为下拉或者级联下拉的结构,提供给前端进行展示. 在数据库查出的结构中,可能是集合<实体类>的结构,也有可能是List<Map>的结构. 在下拉或者级联下拉的节点数据中,有时候还需要动态的携带其他的参数,已便于前端对某些数据的显示 如区域的级联下拉树中,需要携带经纬度的区域–在选择的时候在地图展

  • 基于IE下ul li 互相嵌套时的bug,排查,解决过程以及心得介绍

    检查bug的步骤 1. bug定位 在js脚本中,按照脚本执行的顺序,你可以用console或alert,来确定bug发生的代码区间,然后在区间内进一步来查找bug发生的具体代码段. 2. bug fix 通过排除,就是在插入节点内容的时候导致了bug,我用的是kissy的DOM.html()方法,其功能类似于DOM元素节点innerHTML方法,我起初认为是这个方法导致的IE6\7渲染出错,然后我换成了innerHTML方法,结果还是有误. 这时候我想到了内存泄露,看看是不是在循环拼接字符串的

  • 深入解析C#编程中struct所定义的结构

    结构是使用 struct 关键字定义的,例如: public struct PostalAddress { // Fields, properties, methods and events go here... } 结构与类共享大多数相同的语法,但结构比类受到的限制更多: 在结构声明中,除非字段被声明为 const 或 static,否则无法初始化. 结构不能声明默认构造函数(没有参数的构造函数)或析构函数. 结构在赋值时进行复制.将结构赋值给新变量时,将复制所有数据,并且对新副本所做的任何修

  • C++面试题之结构体内存对齐计算问题总结大全

    前言 本文给大家介绍的是关于C++结构体内存对齐计算的相关内容,内存对齐计算可谓是笔试题的必考题,但是如何按照计算原则算出正确答案一开始也不是很容易的事,所以专门通过例子来复习下关于结构体内存对齐的计算问题.话不多说,来一起看看详细介绍吧. 编译环境:vs2015 对齐原则: 原则1:数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个

  • 深入c# 类和结构的区别总结详解

    类和结构的区别:1.一个是引用类型一个是值类型Class是引用类型,继承自System.Object类Struct是值类型,继承自System.ValueType类,因此不具有多态性因为结构是值类型,所以结构之间赋值可以创建新的结构,复制包含结构的变量时,讲复制所有的数据,对新的副本所作的修改都不会改变旧副本的数据,而类是引用类型,类之间的赋值只是复制引用.2. 继承性的区别Class支持继承,可以继承自类和接口,是完全可扩展的,除非声明sealed.否则类可以继承自其它的类的接口,自身也能被继

  • vue实现的树形结构加多选框示例

    本文实例讲述了vue实现的树形结构加多选框.分享给大家供大家参考,具体如下: 前面说了如何用递归组件来写vue树形结构,写了树形结构还要在前面加多选框,然后往数组里push选项,并在左边显示出来,然后左边进行拖拽排序,拖拽排序上一篇文章我已经介绍过了,在这我就不介绍了,如何用阿里巴巴矢量图标库我也有相关文章,也不介绍了,本节主要介绍vue树形结构加多选框,并实现一定的逻辑,比如全选,单选,全选和单选之间的联动 先看下目录结构 下面我直接贴下代码 首先是pages文件夹中tree.vue页面中引用

  • C++实现的多重继承功能简单示例

    本文实例讲述了C++实现的多重继承功能.分享给大家供大家参考,具体如下: 多重继承 1. 多重继承即一个类继承了多个基类的属性. 2. 多重继承下派生类的构造函数必须同时负责所有基类构造函数的调用, 3. 派生类构造函数的参数个数,必须满足多个基类初始化的需要. 4. 在多重继承下,当建立派生类对象时,系统首先调用各个基类的构造函数,调用顺序与定义派生类时指定的基类顺序一致. 多重继承范例: #include <iostream> /* run this program using the c

  • 关于C#结构体 你需要知道的

    结构体概念 在C#中,结构体是值类型,一般适用于表示类似Point.Rectangle.Color的对象 值类型能够降低对堆的管理.使用.降低垃圾回收,表现出更好的性能.可是值类型也有不好的一面.会涉及到装箱拆箱等操作 结构体声明 结构体声明定义了一种新的数据类型,这个数据类型可以为程序包含一个以上的成员变量 要定义一个结构,需要使用struct语句 声明一个学校的结构 struct School { public int name; public string head_master; pub

  • idea下Android各目录所代表的含义介绍

    1.Project模式结构模式 1..gradle和.idea 这两个目录下都是AndroidStudio自动生成的文件. 2.app 项目中的代码.资源等内容几乎都是放置在这个目录下 3.build 这个目录包含了一些在编译时自动生成的文件. 4.gitignore 这个文件是用来将制定的目录或文件排除在版本控制之外的. 5.build.gradle 这是项目全局的gradle构造脚本 6.gradle.properties 这是项目全局的gradle配置文件 7.gradlew和gradle

随机推荐