C++对象模型5--多继承下的对象模型
C++对象模型中加入多继承
从单继承可以知道,派生类中只是扩充了基类的虚函数表。如果是多继承的话,又是如何扩充的?
1) 每个基类都有自己的虚表。
2) 子类的成员函数被放到了第一个基类的表中。
3) 内存布局中,其父类布局依次按声明顺序排列。
4) 每个基类的虚表中的print()函数都被overwrite成了子类的print ()。这样做就是为了解决不同的基类类型的指针指向同一个子类实例,而能够调用到实际的函数。

上面3个类,Derived_Mutlip_Inherit继承自Base、Base_1两个类,Derived_Mutlip_Inherit的结构如下所示:

为了验证上述C++对象模型,我们编写如下测试代码。
void test_multip_inherit()
{
Derived_Mutlip_Inherit dmi(3333);
cout << "对象dmi的起始内存地址:\t\t" << &dmi << endl;
cout << "虚函数表_vptr_Base地址:\t" << (int*)(&dmi) << endl;
cout << "_vptr_Base — 第1个函数地址:\t" << (int*)*(int*)(&dmi) << "\t即析构函数地址" << endl;
cout << "_vptr_Base — 第2个函数地址:\t" << ((int*)*(int*)(&dmi) + 1) << "\t";
typedef void(*Fun)(void);
Fun pFun = (Fun)*(((int*)*(int*)(&dmi)) + 1);
pFun();
cout << endl;
cout << "_vptr_Base — 第3个函数地址:\t" << ((int*)*(int*)(&dmi) + 2) << "\t";
pFun = (Fun)*(((int*)*(int*)(&dmi)) + 2);
pFun();
cout << endl;
cout << "_vptr_Base — 第4个函数地址:\t" << *((int*)*(int*)(&dmi) + 3) << "【结束】\t";
cout << endl;
cout << "推测数据成员iBase地址:\t\t" << ((int*)(&dmi) +1) << "\t通过地址取得的值:" << *((int*)(&dmi) +1) << endl; SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
cout << "虚函数表_vptr_Base1地址:\t" << ((int*)(&dmi) +2) << endl;
cout << "_vptr_Base1 — 第1个函数地址:\t" << (int*)*((int*)(&dmi) +2) << "\t即析构函数地址" << endl;
cout << "_vptr_Base1 — 第2个函数地址:\t" << ((int*)*((int*)(&dmi) +2) + 1) << "\t";
typedef void(*Fun)(void);
pFun = (Fun)*((int*)*((int*)(&dmi) +2) + 1);
pFun();
cout << endl;
cout << "_vptr_Base1 — 第3个函数地址:\t" << *((int*)*(int*)((int*)(&dmi) +2) + 2) << "【结束】\t";
cout << endl;
cout << "推测数据成员iBase1地址:\t" << ((int*)(&dmi) +3) << "\t通过地址取得的值:" << *((int*)(&dmi) +3) << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
cout << "推测数据成员iDerived地址:\t" << ((int*)(&dmi) +4) << "\t通过地址取得的值:" << *((int*)(&dmi) +4) << endl;
}
输出结果如下图所示:

C++对象模型5--多继承下的对象模型的更多相关文章
- C++学习之路(九):从菱形继承引入的对象模型
一.单继承 class A {int a;}; class B : public A {int b;}; 普通的单继承关系,类的大小是由其虚表指针和非静态成员函数大小决定.故上述sizeof(A)的大 ...
- C++对象模型:单继承,多继承,虚继承,菱形虚继承,及其内存布局图
C++目前使用的对象模型: 此模型下,nonstatic数据成员被置于每一个类的对象中,而static数据成员则被置于类对象之外,static和nonstatic函数也都放在类对象之外(通过函数指针指 ...
- C++ //继承中的对象模型 //利用开发人员命令提示工具查看对象模型 //父类中所有非静态成员属性都会被 子类继承下去 //父类中私有成员属性 是被编译器给隐藏了 因此是访问不到 但是确实被继承下去了
1 //继承方式 2 //语法:class 子类 :继承方式 父类 3 //继承方式 三种: 4 //1.公共继承 5 //2.保护继承 6 //3.私有继承 7 8 /* 9 #include &l ...
- sqlalchemy mark-deleted 和 python 多继承下的方法解析顺序 MRO
sqlalchemy mark-deleted 和 python 多继承下的方法解析顺序 MRO 今天在弄一个 sqlalchemy 的数据库基类的时候,遇到了跟多继承相关的一个小问题,因此顺便看了一 ...
- JS中的继承(下)
JS中的继承(下) 在上一篇 JS中的继承(上) 我们介绍了3种比较常用的js继承方法,如果你没看过,那么建议你先看一下,因为接下来要写的内容, 是建立在此基础上的.另外本文作为我个人的读书笔记,才疏 ...
- C++ 链式继承下的虚函数列表
目录 1.虚函数列表的位置 2.虚函数列表的内容 3.链式继承中虚函数列表的内容 注: 虚函数列表 又称为虚表, vtbl , 指向它的指针称为vptr, vs2019中称为__vfptr 操作系 ...
- C++对象模型——"无继承"情况下的对象构造(第五章)
5.1 "无继承"情况下的对象构造 考虑以下这个程序片段: 1 Point global; 2 3 Point foobar() 4 { 5 Point local; 6 Poin ...
- C++对象模型:单继承,多继承,虚继承
什么是对象模型 有两个概念可以解释C++对象模型: 语言中直接支持面向对象程序设计的部分.对于各种支持的底层实现机制. 类中成员分类 数据成员分为静态和非静态,成员函数有静态非静态以及虚函数 clas ...
- C++对象模型的那些事儿之一:对象模型(上)
前言 很早以前就听人推荐了<深入理解C++对象模型>这本书,从年初买来到现在也只是偶尔翻了翻,总觉得晦涩难懂,放在实验室上吃灰吃了好久.近期由于找工作对C++的知识做了一个全面系统的学习, ...
随机推荐
- Paxos算法小结
转自不正直的绅士,因百度空间迁移,无法注明出处,我从其google搜索引擎中的cache进行的copy. 不正直的绅士 是跟我一起工作过的非常有才的一个青年才俊. Paxos的使用非常广泛.sanlo ...
- C++_bool
1 0 #include <iostream> using namespace std; void main() { && || || - && ; std ...
- selector是在文件夹drawable中进行定义的xml文件。
获取Drawable对象: Resources res = mContext.getResources(); Drawable myImage = res.getDrawable(R.drawable ...
- 通过案例掌握Spring 管理事务的步骤及配置
案例描述 通过完成生成订单业务,掌握事务处理. 需要d_order表和d_item表 订单生成时的业务逻辑:向d_order插入1条数据的同时,向t_item中插入若干条数据 这就是一个独立的 ...
- SQL学习之SELECT子句顺序
下面来总计下之前的随笔中所说过的所有的SELECT子句的顺序. 子句 说明 是否必须使用 SELECT 要返回的列或者表达式 ...
- localhost简介、localhost与 127.0.0.1 及 本机IP 的区别
localhost是什么意思? 相信有人会说是本地ip,曾有人说,用127.0.0.1比localhost好,可以减少一次解析. 看来这个入门问题还有人不清楚,其实这两者是有区别的. localhos ...
- JavaSE复习日记 : 多态
/** * 里氏替换原则 : * 能使用父类的地方,一定可以使用子类 * 什么是多态 : * 父类的引用,指向子类的对象 * 多态的前提条件 : * 有继承关系的两个类 * 多态的目的 : * ☆☆☆ ...
- 将窗口置顶的方法:SetWindowPos、AttachThreadInput、SwitchToThisWindow
将窗口置顶的方法:SetWindowPos.AttachThreadInput.SwitchToThisWindow [转]http://hi.baidu.com/neil_danky/item/f9 ...
- Hibernate学习之关系映射(转)
一.一对多 "一对多"是最普遍的映射关系,简单来讲就如消费者与订单的关系.一对多:从消费者角的度来说一个消费者可以有多个订单,即为一对多.多对一:从订单的角度来说多个订单可以对应一 ...
- 1 2 5 10 20 --> 800
用1元 2元 5元 10元 20元的钞票凑成800元的方法种数计算,使用了动态规划. 结果没打出来,只是保留在函数里各个vector中,调试可看所有结果. 优点:快 缺点:占空间占内存 耗时时间测试: ...