关于C++ 多态实现技术的深度解析(vfptr,vftable)
PS:要转载请注明出处,本人版权所有。
PS: 这个只是基于《我自己》的理解,
如果和你的原则及想法相冲突,请谅解,勿喷。
前置说明
本文作为本人csdn blog的主站的备份。(BlogID=059)
本文发布于 2018-04-04 17:05:21,现用MarkDown+图床做备份更新。blog原图已丢失,使用csdn所存的图进行更新。(BlogID=059)
环境说明
无
前言
关于C++的多态,我就不多说了,我理解的一句话就是:一个接口,多种实现(简称:一对多)。在C++里面,多态的最重要的实现方法为继承,简单来说:就是基类提供接口,子类可以实现基类的接口,不同的子类就构成了基类接口的不同的实现。以上就是C++课本上或者C++原理上的常见的知识。
而今天这里所说明的是多态是怎么实现的,以及实现的详细方法。我个人认为:只有了解了这些东西后,我们才不会在多态中迷失自己的方向,导致代码稀烂。
c++ 多态
多态的实现
多态的实现是通过一个指针数组实现的。此指针数组的一般声明如下:
//虚函数表
void ** vfptr;//此ptr指向一个void * 的数组
说明: vfptr 变量的声明是C++编译器根据:当一个带有虚函数的类定义了一个实例时,编译器会自动在此类的前4bytes(32bit 系统)添加vfptr变量来实现多态。同时编译器会生成一个void *数组来存放实际接口方法地址(其实这里就已经实现了多态,也就是说:这里就已经定义好了这个实例可以调用哪些实际接口方法,例如是来至于基类还是子类等等),也就是虚函数表(vftable),此表是放在生成的可执行文件的数据段。
总结:这里有一些基本的习惯。
- vfptr放在一个类的起始相关地址。
- vftable中的方法按照继承顺序、接口声明顺序赋值。
以上都是自己瞎扯的原理,看不懂也没有啥问题,毕竟我的语文水平不高,语言组织能力不行,直接跳过查看下面的实例分析。
多态的实现原理解析实例
class Base
{
public:
Base() {}
~Base() {}
virtual void base1(void) = 0;
virtual void base2(void) {};
virtual void base3(void) {};
int base_a = 0;
private:
};
class Base1
{
public:
Base1() {}
~Base1() {}
virtual void base2(void) {};
virtual void base3(void) {};
int base_a = 0;
private:
};
class Derive:public Base
{
public:
Derive() {}
~Derive() {}
virtual void base1(void) {}
virtual void base2(void) {}
int derive_a = 1;
private:
};
class Derive1 :public Base
{
public:
Derive1() {}
~Derive1() {}
virtual void base1(void) {}
virtual void base2(void) {}
virtual void derive1(void) {}
virtual void derive2(void) {}
int derive_a = 2;
private:
};
class Derive2:public Derive1
{
public:
Derive2() {}
~Derive2() {}
virtual void derive1(void) {}
private:
};
int main()
{
Base1 b1;
Derive d1;
Derive1 dd1;
Derive2 ddd1;
return 0;
}
20200306 动态绑定的补充
关于派生对象地址赋值给基类指针 并使用基类指针调用派生类函数。源码如下:
(20200326补充END)
以下是vs2015的调试分析截图:(若只想了解一下vfptr和vftable是个什么样子,只看此图并结合代码分析足以)
友情提示:此图中关于ddd1的vfptr和我们想要的结果是不同的,原因和调试器相关,具体关于ddd1哪里有问题,若有需求,请看以下分析。
多态的实现原理解析实例(进阶版)
同上一份代码,我们深入到汇编里面,就可以发现一些我们不知道的细节,关于这些汇编中的其他内容部分,若想了解,参考此文章:https://blog.csdn.net/u011728480/article/details/79092194。
这里我们只分析变量ddd1的生成过程。
用ida载入我们生成的exe文件。找到main函数中ddd1初始化入口如下:
20200306 动态绑定的补充
关于派生对象地址赋值给基类指针 并使用基类指针调用派生类函数。反汇编如下:
ddd1对象的vfptr如下:
可以发现动态绑定的时候,基类指针的vfptr已经指向了ddd1对象的vfptr。
(20200326补充END)
这里我们跳转到call后面的地址查看Derive2的构造函数,先调用Derive1的构造函数,再给vfptr赋值。下图是构造函数汇编
下图是vfptr的赋值内容,也就是vftable是什么样子的
这里可以看到,其实此实例调用的是哪些方法(也就实现了多态),早已经在编译时就确定了,只是这里才赋值而已,所以可以说是动态绑定或者静态绑定。
下图为Derive1构造函数以及vftable值:
下图为Base构造函数以及vftable的值:
以上总结:我们可以发现vfptr经过了多次赋值的,不同的时间段,vfptr值不一样,所以在构造实例的时候,不同时段调用同一个接口,会有不同的方法。
同时也可以得出一个结论,每个接口的实现类都有一个虚函数表,包括接口类本身,这些虚函数表在编译时就确定了,只是vfptr赋值的时候,是在程序运行时确定的。
根据以上的分析,可以解决许多我们关于多态的疑问。
后记
无
参考文献
- 无
打赏、订阅、收藏、丢香蕉、硬币,请关注公众号(攻城狮的搬砖之路)
PS: 请尊重原创,不喜勿喷。
PS: 要转载请注明出处,本人版权所有。
PS: 有问题请留言,看到后我会第一时间回复。
关于C++ 多态实现技术的深度解析(vfptr,vftable)的更多相关文章
- 华为全栈AI技术干货深度解析,解锁企业AI开发“秘籍”
摘要:针对企业AI开发应用中面临的痛点和难点,为大家带来从实践出发帮助企业构建成熟高效的AI开发流程解决方案. 在数字化转型浪潮席卷全球的今天,AI技术已经成为行业公认的升级重点,正在越来越多的领域为 ...
- 深度解析SDN——利益、战略、技术、实践(实战派专家力作,业内众多专家推荐)
深度解析SDN——利益.战略.技术.实践(实战派专家力作,业内众多专家推荐) 张卫峰 编 ISBN 978-7-121-21821-7 2013年11月出版 定价:59.00元 232页 16开 ...
- Deep Learning模型之:CNN卷积神经网络(一)深度解析CNN
http://m.blog.csdn.net/blog/wu010555688/24487301 本文整理了网上几位大牛的博客,详细地讲解了CNN的基础结构与核心思想,欢迎交流. [1]Deep le ...
- (转载)(收藏)OceanBase深度解析
一.OceanBase不需要高可靠服务器和高端存储 OceanBase是关系型数据库,包含内核+OceanBase云平台(OCP).与传统关系型数据库相比,最大的不同点, 是OceanBase是分布式 ...
- Kafka深度解析
本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/01/02/Kafka深度解析 背景介绍 Kafka简介 Kafka是一种分布式的,基于发布/订阅 ...
- Unity加载模块深度解析(Shader)
作者:张鑫链接:https://zhuanlan.zhihu.com/p/21949663来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 接上一篇 加载模块深度解析(二 ...
- Unity加载模块深度解析(网格篇)
在上一篇 加载模块深度解析(一)中,我们重点讨论了纹理资源的加载性能.这次,我们再来为你揭开其他主流资源的加载效率. 这是侑虎科技第53篇原创文章,欢迎转发分享,未经作者授权请勿转载.同时如果您有任何 ...
- 汇顶指纹传感器GF919深度解析
前言: 随着指纹识别技术的日益普遍,其在手机上的应用也得到了广泛关注.作为全球第一款Android正面按压指纹识别手机,魅族MX4 Pro所搭载的国产指纹识别系统可谓是赚足了眼球,这就是由汇顶科技提供 ...
- mybatis 3.x源码深度解析与最佳实践(最完整原创)
mybatis 3.x源码深度解析与最佳实践 1 环境准备 1.1 mybatis介绍以及框架源码的学习目标 1.2 本系列源码解析的方式 1.3 环境搭建 1.4 从Hello World开始 2 ...
- 蓝鲸DevOps深度解析系列(2):蓝盾流水线初体验
关注嘉为科技,获取运维新知 前面一篇文章<蓝鲸DevOps深度解析系列(1):蓝盾平台总览>,我们总览了蓝鲸DevOps平台的背景.应用场景.特点和能力: 接下来我们继续解析蓝盾平台的 ...
随机推荐
- P5501 [LnOI2019] 来者不拒,去者不追 题解
题目链接:来者不拒,去者不追 直接在线查询题目所给的式子是很困难的,我们考虑单点考察贡献.对于一个已经确定的式子,我们发现加入一个数或者删除一个数的贡献如图所示: 如图所示,在原有的序列为 \((1, ...
- 5个.NET开源且强大的快速开发框架(帮助你提高生产效率)
中台Admin(Admin.Core) 中台Admin(Admin.Core)是前后端分离权限管理系统,前端 UI 基于Vue3开发,后端 Api 基于.NET 8.0开发.支持多租户.接口权限.数据 ...
- 设计模式(三十二)----综合应用-自定义Spring框架-自定义Spring IOC-自定义Spring IOC总结
1 自定义Spring IOC总结 1.1 使用到的设计模式 工厂模式.这个使用工厂模式 + 配置文件的方式. 单例模式.Spring IOC管理的bean对象都是单例的,此处的单例不是通过构造器进行 ...
- Oracle 19c RAC自动应用RU补丁过程
笔者好久没有使用opatchauto打过补丁了,搜了下自己的历史随笔,上次opatchauto打补丁的记录还是Oracle 11g版本: Oracle 11g RAC 自动应用PSU补丁简明版 而11 ...
- 写好C#代码的技巧
写好C#代码的技巧 编者导语 本文来自https://www.pluralsight.com,作者Afzaal Ahmad Zeeshan. 原文包含以下三篇文章: <编写更好的C#代码简介&g ...
- JS leetcode 删除排序数组中的重复项 题解分析
壹 ❀ 引 一日一题,今天的题目来自于leetcode26. 删除排序数组中的重复项,其实在之前我们已经做了一道类似的题目,可参考JS leetcode 移除元素 题解分析,关于本题描述如下: 给定一 ...
- NC20545 [HEOI2012]采花
题目链接 题目 题目描述 萧芸斓是Z国的公主,平时的一大爱好是采花. 今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花. 花园足够大,容纳了 \(n\) 朵花,花有 \(c\) 种颜色(用整 ...
- NC19996 [HAOI2015]树上染色
题目链接 题目 题目描述 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染成白色. 将所有点染色后,你会获得黑点两两之间的 ...
- Centos7和Centos8的NFS配置
Centos7和Centos8的NFS配置几乎是完全一样的 服务端 Centos7默认安装了rpcbind, nfs-utils, 其中rpcbind的服务默认是启用的, nfs-utils默认是禁用 ...
- 解决:EXP-00003: 未找到段 (0,0) 的存储定义报错
问题说明 DB服务器oracle版本:11.2.0.4.0 最近在客户端用exp命令导出部分表时报错,如题.搜索了一下,找到以下解决方案: 问题原因 Oracle 11g 有一个参数deferred_ ...