C++ 虚函数表与多态 —— 多重继承的虚函数表 & 内存布局
多重继承的虚函数表会有两个虚表指针,分别指向两个虚函数表,如下代码中的 vptr_s_1、vptr_s_2,Son类继承自 Father 和 Mather 类,并且改写了 Father::func_1 与 Mather::handle_1,这两个虚函数将会存放到两个虚函数表中,Son 新加的 func_4 将会在第一个虚函数表中:
1 #include <iostream>
2 using namespace std;
3
4 class Father
5 {
6 public:
7 virtual void func_1() { cout << "Father::func_1" << endl; }
8 virtual void func_2() { cout << "Father::func_2" << endl; }
9 virtual void func_3() { cout << "Father::func_3" << endl; }
10 public:
11 int x = 666;
12 int y = 999;
13 };
14
15 class Mother
16 {
17 public:
18 virtual void handle_1() { cout << "Mother::handle_1" << endl; }
19 virtual void handle_2() { cout << "Mother::handle_2" << endl; }
20 virtual void handle_3() { cout << "Mother::handle_3" << endl; }
21 public:
22 int a = 555;
23 int b = 888;
24 };
25
26 class Son : public Father, public Mother //继承了两个父类
27 {
28 public:
29 void func_1() { cout << "Son::func_1" << endl; } //重写了 Father 虚函数
30 virtual void func_4() { cout << "Son::func_4" << endl; } //子类对象新写的虚函数 func_4
31 void handle_1() { cout << "Son::handle_1" << endl; } //重写了 Mother 虚函数
32 };
33
34 typedef void(*func_t)(void);
35
36 int main(void)
37 {
38 Son son;
39 int* vptr_s_1 = (int*)*(int*)&son; //son的第一个虚表指针
40
41 for (int i = 0; i < 4; i++)
42 {
43 cout << "调用第" << i + 1 << "个虚函数:";
44 ((func_t) * (vptr_s_1 + i))();
45 }
46
47 for (int i = 0; i < 2; i++)
48 {
49 cout << "继承自 Father 数据成员:" << *(int*)((int)&son + 4 + i * 4) << endl;
50 }
51
52 int* vptr_s_2 = (int*)*((int*)&son + 3); //son的第二个虚表指针
53 for (int i = 0; i < 3; i++)
54 {
55 cout << "调用第" << i + 1 << "个虚函数:";
56 ((func_t) * (vptr_s_2 + i))();
57 }
58
59 for (int i = 0; i < 2; i++)
60 {
61 cout << "继承自 Mather 数据成员:" << *(int*)((int)&son + 16 + i * 4) << endl;
62 }
63 }
打印结果:

使用VS编译器来打印内存布局,方法如下:
项目的命令行配置中添加: /d1 reportSingleClassLayoutSon
项目属性 -> 配置属性 -> C/C++ -> 命令行
编译代码后的输出打印:

由此也可得知,多重继承的虚函数表结构如下图:

===========================================================================================================================
C++ 虚函数表与多态 —— 多重继承的虚函数表 & 内存布局的更多相关文章
- 继承虚函数浅谈 c++ 类,继承类,有虚函数的类,虚拟继承的类的内存布局,使用vs2010打印布局结果。
本文笔者在青岛逛街的时候突然想到的...最近就有想写几篇关于继承虚函数的笔记,所以回家到之后就奋笔疾书的写出来发布了 应用sizeof函数求类巨细这个问题在很多面试,口试题中很轻易考,而涉及到类的时候 ...
- C++ 虚函数表与多态 —— 继承的虚函数表 & 内存布局
1. 使用继承的虚函数表: 如果不涉及多重继承,每个类只有1个虚函数表,当子类继承父类后,子类可以自己改写和新增虚函数,如下图所示: 子类重写 func_1 后,子函数的 func_1 将会有新的逻辑 ...
- 浅析GCC下C++多重继承 & 虚拟继承的对象内存布局
继承是C++作为OOD程序设计语言的三大特征(封装,继承,多态)之一,单一非多态继承是比较好理解的,本文主要讲解GCC环境下的多重继承和虚拟继承的对象内存布局. 一.多重继承 先看几个类的定义: 01 ...
- C++对象模型 多重继承与虚函数表
一 多重继承 1) 代码: Code#include <iostream>using namespace std; class B1{public: int x; virtua ...
- [C++对象模型][8]多重继承与虚函数表
转载: [C++对象模型][8]多重继承与虚函数表 一 多重继承 1) 代码: Code #include <iostream> using namespace std; class B1 ...
- C++ 虚函数表与多态 —— 虚函数表的内存布局
C++面试经常会被问的问题就是多态原理.如果对C++面向对象本质理解不是特别好,问到这里就会崩. 下面从基本到原理,详细说说多态的实现:虚函数 & 虚函数表. 1. 多态的本质: 形 ...
- 虚函数表-C++多态的实现原理
目录 1.说明 2.虚函数表 3.代码示例 参考:http://c.biancheng.net/view/267.html 1.说明 我们都知道多态指的是父类的指针在运行中指向子类,那么它的实现原理是 ...
- C++对象的内存布局以及虚函数表和虚基表
C++对象的内存布局以及虚函数表和虚基表 本文为整理文章, 参考: http://blog.csdn.net/haoel/article/details/3081328 http://blog.csd ...
- vs查看虚函数表和类内存布局
虚继承和虚基类 虚继承:在继承定义中包含了virtual关键字的继承关系: 虚基类:在虚继承体系中的通过virtual继承而来的基类,需要注意的是:class CSubClass : publ ...
随机推荐
- 删除ceph集群mds
ceph集群新搭建以后是只有一个默认的存储池rbd的池 ## 创建文件接口集群 1.创建一个元数据池 [root@mytest ~]# ceph osd pool create metadata 20 ...
- ubuntu配置bonding
如果节点上有多个网络接口时可以通过bonding将多个网络接口虚拟为一个网络接口,bonding可以提供高可用及负载均衡功能,从而提高节点的网络接口性能及可用性. 配置单bond 一.使用如下命令安装 ...
- Linux内核源码分析之set_arch (一)
1. 概述 之前已经写了几篇Linux内核启动相关的文章,比如:<解压内核镜像><调用 start_kernel>都是用汇编语言写的,这些代码的作用仅仅是把内核镜像放置到特定的 ...
- webpack 无法打包:No configuration file found and no output filename configured via CLI option
报错内容 No configuration file found and no output filename configured via CLI option.A configuration fi ...
- 下载器Folx的创建种子功能怎么使用
当我们想要分享一些自己制作的资源时,可以使用Folx的创建种子功能,在网络上分享种子,供他人下载,这个过程也被称为做种.作为种子创建者,需要在一定时间内保持做种进程,以便维持种子的生命期限,方便他人下 ...
- VueCli 4.0+ 版本安装插件与VueCLI 旧版本的不同
通过VueCli 脚手架 4+ 版本创建的项目,在引入插件文件并配置时,是通过 import {Create* } ,旧版本是直接导入全部,在配置相应的文件时,重新new 一个:然后再通过Vue 进行 ...
- CSS3 学习笔记(上)
一.CSS简介 CSS(Cascading Style Sheets)层叠样式表.其中,样式定义为如何显示HTML元素,它通常储存在样式表,将样式添加到HTML中,能够解决内容与表现分离的问题.由于网 ...
- C语言讲义——字符串
字符数组 C语言字符串就是字符数组. 单写字符,用单引号.如:'A'. 字符串用双引号.如:"A"."ABC". #include <stdio.h> ...
- Java基础教程——网络基础知识
参考阅读[中国互联网发展史]:https://zhuanlan.zhihu.com/p/61602252 协议 计算机网络中的通信必须有一些约定,这些约定称为"通信协议". 通信协 ...
- Java基础教程——线程池
启动新线程,需要和操作系统进行交互,成本比较高. 使用线程池可以提高性能-- 线程池会提前创建大量的空闲线程,随时待命执行线程任务.在执行完了一个任务之后,线程会回到空闲状态,等待执行下一个任务.(这 ...