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--多继承下的对象模型的更多相关文章

  1. C++学习之路(九):从菱形继承引入的对象模型

    一.单继承 class A {int a;}; class B : public A {int b;}; 普通的单继承关系,类的大小是由其虚表指针和非静态成员函数大小决定.故上述sizeof(A)的大 ...

  2. C++对象模型:单继承,多继承,虚继承,菱形虚继承,及其内存布局图

    C++目前使用的对象模型: 此模型下,nonstatic数据成员被置于每一个类的对象中,而static数据成员则被置于类对象之外,static和nonstatic函数也都放在类对象之外(通过函数指针指 ...

  3. C++ //继承中的对象模型 //利用开发人员命令提示工具查看对象模型 //父类中所有非静态成员属性都会被 子类继承下去 //父类中私有成员属性 是被编译器给隐藏了 因此是访问不到 但是确实被继承下去了

    1 //继承方式 2 //语法:class 子类 :继承方式 父类 3 //继承方式 三种: 4 //1.公共继承 5 //2.保护继承 6 //3.私有继承 7 8 /* 9 #include &l ...

  4. sqlalchemy mark-deleted 和 python 多继承下的方法解析顺序 MRO

    sqlalchemy mark-deleted 和 python 多继承下的方法解析顺序 MRO 今天在弄一个 sqlalchemy 的数据库基类的时候,遇到了跟多继承相关的一个小问题,因此顺便看了一 ...

  5. JS中的继承(下)

    JS中的继承(下) 在上一篇 JS中的继承(上) 我们介绍了3种比较常用的js继承方法,如果你没看过,那么建议你先看一下,因为接下来要写的内容, 是建立在此基础上的.另外本文作为我个人的读书笔记,才疏 ...

  6. C++ 链式继承下的虚函数列表

    目录 1.虚函数列表的位置 2.虚函数列表的内容 3.链式继承中虚函数列表的内容   注: 虚函数列表 又称为虚表, vtbl , 指向它的指针称为vptr, vs2019中称为__vfptr 操作系 ...

  7. C++对象模型——&quot;无继承&quot;情况下的对象构造(第五章)

    5.1 "无继承"情况下的对象构造 考虑以下这个程序片段: 1 Point global; 2 3 Point foobar() 4 { 5 Point local; 6 Poin ...

  8. C++对象模型:单继承,多继承,虚继承

    什么是对象模型 有两个概念可以解释C++对象模型: 语言中直接支持面向对象程序设计的部分.对于各种支持的底层实现机制. 类中成员分类 数据成员分为静态和非静态,成员函数有静态非静态以及虚函数 clas ...

  9. C++对象模型的那些事儿之一:对象模型(上)

    前言 很早以前就听人推荐了<深入理解C++对象模型>这本书,从年初买来到现在也只是偶尔翻了翻,总觉得晦涩难懂,放在实验室上吃灰吃了好久.近期由于找工作对C++的知识做了一个全面系统的学习, ...

随机推荐

  1. 基于Java图片数据库Neo4j 3.0.0发布 全新的内部架构

    基于Java图片数据库Neo4j 3.0.0发布 全新的内部架构 Neo4j 3.0.0 正式发布,这是 Neo4j 3.0 系列的第一个版本.此版本对内部架构进行了全新的设计;提供给开发者更强大的生 ...

  2. Qt通过Http上传文件(路过)

    web端: <?php $c = $GLOBALS['HTTP_RAW_POST_DATA']; $n = $_GET["filename"]; $fp = fopen($n ...

  3. 面向对象程序设计-C++_课时16子类父类关系

    初始化列表 类名::类名(形参1,形参2,...形参n):数据成员1(形参1),数据成员2(形参2),...,数据成员n(形参n) { ... } 规则1,初始化列表进行数据成员的初始化 规则2,初始 ...

  4. HDOJ 4252 A Famous City 单调栈

    单调栈: 维护一个单调栈 A Famous City Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (J ...

  5. JS学习笔记(一)基本数据类型和对象类型

    js是一种弱类型的语言,所有的变量都用var进行声明,字符串用双引号或单引号括起来,常见基本数据类型为number,string,boolean等.如 var num = 123;或var num = ...

  6. Oracle死锁。

    oracle数据库死锁一般情况下在oracle数据库中不会.但是在程序中可以开启事物没有提交,但是程序报错我们就关了程序在重新调试.但是我们程序总是在执行 comm.ExecuteNonQuery() ...

  7. IE 对象不支持“attachEvent”属性或方法

    解决方法:attachEvent 是很旧的非标准方法.请使用 addEventListener.

  8. 穿透的 div ( pointer-events )

    pointer-events 是一個滿有趣的 CSS3 屬性,雖然主要是針對 SVG ,但其中幾個屬性應用在 div 上也是頗有意思.顧名思義,這是一個針對滑鼠事件的屬性,預設值為 auto,若值為 ...

  9. Spring——AOP(面向切面编程)@AspectJ注解方式

    一.什么是AOP? AOP: (Aspect Oriented Programming)即面向切面编程. 试想这样的场景:项目中需要在业务方法执行完打印日志记录.最笨的办法就是在每个方法核心业务执行完 ...

  10. js跨域及解决方法

    什么是跨域 JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象.但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦.这里把涉及到跨域的一些问题简单地整理一下: 首 ...