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++的知识做了一个全面系统的学习, ...
随机推荐
- 基于Java图片数据库Neo4j 3.0.0发布 全新的内部架构
基于Java图片数据库Neo4j 3.0.0发布 全新的内部架构 Neo4j 3.0.0 正式发布,这是 Neo4j 3.0 系列的第一个版本.此版本对内部架构进行了全新的设计;提供给开发者更强大的生 ...
- Qt通过Http上传文件(路过)
web端: <?php $c = $GLOBALS['HTTP_RAW_POST_DATA']; $n = $_GET["filename"]; $fp = fopen($n ...
- 面向对象程序设计-C++_课时16子类父类关系
初始化列表 类名::类名(形参1,形参2,...形参n):数据成员1(形参1),数据成员2(形参2),...,数据成员n(形参n) { ... } 规则1,初始化列表进行数据成员的初始化 规则2,初始 ...
- HDOJ 4252 A Famous City 单调栈
单调栈: 维护一个单调栈 A Famous City Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (J ...
- JS学习笔记(一)基本数据类型和对象类型
js是一种弱类型的语言,所有的变量都用var进行声明,字符串用双引号或单引号括起来,常见基本数据类型为number,string,boolean等.如 var num = 123;或var num = ...
- Oracle死锁。
oracle数据库死锁一般情况下在oracle数据库中不会.但是在程序中可以开启事物没有提交,但是程序报错我们就关了程序在重新调试.但是我们程序总是在执行 comm.ExecuteNonQuery() ...
- IE 对象不支持“attachEvent”属性或方法
解决方法:attachEvent 是很旧的非标准方法.请使用 addEventListener.
- 穿透的 div ( pointer-events )
pointer-events 是一個滿有趣的 CSS3 屬性,雖然主要是針對 SVG ,但其中幾個屬性應用在 div 上也是頗有意思.顧名思義,這是一個針對滑鼠事件的屬性,預設值為 auto,若值為 ...
- Spring——AOP(面向切面编程)@AspectJ注解方式
一.什么是AOP? AOP: (Aspect Oriented Programming)即面向切面编程. 试想这样的场景:项目中需要在业务方法执行完打印日志记录.最笨的办法就是在每个方法核心业务执行完 ...
- js跨域及解决方法
什么是跨域 JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象.但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦.这里把涉及到跨域的一些问题简单地整理一下: 首 ...