【C++】虚函数的实现机制
一.什么是虚函数?
虚函数是在类中由virtual关键字声明的成员函数,并且每一个含有虚函数的类都至少有一个与之对应的虚函数表,其中存放着该类所有虚函数对应的函数指针
在基类中进行如下定义:
virtual void show() //由于有virtual修饰所以是虚函数
void show()//虽然和前面声明的show虚函数同名,但不是虚函数

- B的虚函数表中存放着B::foo和B::bar两个函数指针。
- D的虚函数表中存放的既有继承自B的虚函数B::foo,又有重写(override)了基类虚函数B::bar的D::bar,还有新增的虚函数D::quz。
所有虚函数地址都会存放在所属类的虚函数表vtbl中,另外在基类中声明为虚函数的成员方法,达到子类是仍然是虚函数,即使子类中重新定义基类虚函数时未使用virtual修饰,该函数地址仍会放在子类的虚函数表vtbl中
二.虚函数表是如何构造和继承的?
1)基类虚函数表的构造:
首先在基类声明中找到所有虚函数,按照其声明顺序编码,然后按照此声明顺序为基类创建一个虚函数表,其内容就是指向这些虚函数的函数指针,按照虚函数声明的顺序将这些虚函数的地址填入虚函数表中,例如若show放在虚函数声明的第二位,则在虚函数表中也放第二位
2)子类虚函数表的构建和继承:
首先将基类的虚函数表复制到该子类的虚函数表指针中,若子类重写了基类的虚函数show,则将子类的虚函数表存放show的函数地址更新未重写后函数的函数指针(未重写前存放的是子类的show虚函数的函数地址),若子类增加了一些虚函数的声明,则将这些虚函数的地址加到该类虚函数表的后面

三.虚函数的调用过程/虚函数表是如何访问的?
基类 Base::virtualvoid show(); (1)
子类 Extend::virtualvoid show(); (2)
Extern ext;
Base*pBase=&ext;
pBase->show();
当指向pBase->show()时,要观察show在Base基类中声明的是虚函数还是非虚函数,若为虚函数将使用动态联编(使用虚函数表决定如何调用函数),若为非虚函数则使用静态联编(根据调用指针pBase的类型来确定调用哪个类的成员函数),此处show为虚函数,首先由于检查到PBase指针类型所指的类Base中show定义为虚函数,因此找到pBase所指对象(有可能是Base类型也有可能是Extern类型),访问对象得到该对象的所属类虚函数地址表,其次,查找show在Base类中声明的位置以此找到其在show在Base类中所有虚函数声明中的位序,然后到pBase所指对象的所属类的虚函数表中访问该位序的函数指针,从而得到要执行的函数
当执行pBase->show();时首先到Base中查看show(),发现其为虚函数,然后访问pBase指向的ext对象,在对象中得到Extend类的虚函数表,在Base类声明中找到show()声明的位序0,访问Extend类的虚函数表的位置0,得到show的函数地址。注意若只有基类定义了virtual void show();而子类未重写virtual void show();即上面的函数(2),则Extend虚函数表中的位序0中存放的地址仍然是Base类中定义的virtual void show()函数,而若Extend类中重写了Base类中的virtual void show()方法,则Extend的虚函数表中位序0的函数地址将被更新为Extend中新重写的函数地址。从而调用pBase->show()时将产生多态的现象。
总结:当调用pBase->show();时,执行的步骤:
1.判断Base类中show是否为虚函数。
2.若不是虚函数则找到pBase所指向的对象所属类Base。执行Base::show()。若是虚函数则执行步骤3.
3.访问pBase所指对象的虚函数表指针得到pBase所指对象所在类的虚函数表。
4.查找Base中show()在声明时的位序为x,到步骤3得到的虚函数表中找到位序x,从而得到要执行的show的函数地址。
5.根据函数地址和Base中声明的show的函数类型(形参和返回值)访问地址所指向的函数。
无论pBase指向哪种类型的对象,只要能够确定被调函数在虚函数中的偏移值,待运行时,能够确定具体类型,并能找到相应vptr了,就能找出真正应该调用的函数。
【C++】虚函数的实现机制的更多相关文章
- C++虚函数的实现机制示例
C++虚函数的实现机制是通过一个vtable表,指向子类的虚函数地址. 另外,如果不是虚函数,则不能实现用父类引用调用子类方法. #include <windows.h> #include ...
- C++中的虚函数(表)实现机制以及用C语言对其进行的模拟实现
tfref 前言 C++对象的内存布局 只有数据成员的对象 没有虚函数的对象 拥有仅一个虚函数的对象 拥有多个虚函数的对象 单继承且本身不存在虚函数的继承类的内存布局 本身不存在虚函数(不严谨)但存在 ...
- C++中虚函数功能的实现机制
要理解C++中虚函数是如何工作的,需要回答四个问题. 1. 什么是虚函数. 虚函数由于必须是在类中声明的函数,因此又称为虚方法.所有以virtual修饰符开始的成员函数都成为虚方法.此时注意是vir ...
- c++虚函数实现机制(转)
前言 C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有“多种形态”,这是一种泛 ...
- [C/C++] 虚函数机制
转自:c++ 虚函数的实现机制:笔记 1.c++实现多态的方法 其实很多人都知道,虚函数在c++中的实现机制就是用虚表和虚指针,但是具体是怎样的呢?从more effecive c++其中一篇文章里面 ...
- [转载]C++虚函数浅析
原文:http://glgjing.github.io/blog/2015/01/03/c-plus-plus-xu-han-shu-qian-xi/ 感谢:单刀土豆 C++虚函数浅析 JAN 3RD ...
- [CareerCup] 13.3 Virtual Functions 虚函数
13.3 How do virtual functions work in C++? 这道题问我们虚函数在C++中的工作原理.虚函数的工作机制主要依赖于虚表格vtable,即Virtual Table ...
- 关于C++与Java中虚函数问题的读书笔记
之前一直用C++编程,对虚函数还是一些较为肤浅的理解.可近期由于某些原因搞了下Java,发现有些知识点不熟,于是站在先驱巨人的肩上谈谈C++与Java中虚函数问题. Java中的虚函数 以下是段别人的 ...
- C++ 虚函数详解
C++ 虚函数详解 这篇文章主要是转载的http://blog.csdn.net/haoel/article/details/1948051这篇文章,其中又加入了自己的理解和难点以及疑问的解决过程,对 ...
随机推荐
- 响应式开发 纯CSS实现隐藏菜单栏
// 将要隐藏的菜单设置 display: block; // 然后在菜单上面设置一个点击选项,如“菜单”<label for="toggle-checkbox" id=&q ...
- iOS 原生推送(APNS)的实现
1.前期准备工作 创建你的APNs keys 或者 创建推送证书,这两个创建一个即可实现推送.这两个创建一个即可实现推送.这两个创建一个即可实现推送.重要的事情说三遍,我看评论区有小伙伴误解. 1. ...
- FPM十一:点击POPUP显示明细
沿接着前面的Search和List.在LIST中点击一列,弹出窗口显示明细. 1.list中定义事件: METHOD if_fpm_guibb_list~get_definition. DATA:gt ...
- FPM八:FPM TREE
先上效果图: 1,新建类:ZCL_FPM_TREE,并添加接口:IF_FPM_GUIBB,IF_FPM_GUIBB_TREE.激活所有方法 2.定义tree结构,在class的public secti ...
- 剑指:求1+2+…+n
题目描述 求 1+2+…+n,要求不能使用 乘除法.for.while.if.else.switch.case 等关键字及条件判断语句 A?B:C. 样例 输入:10 输出:55 解法 前面的和+后一 ...
- Ueditor文字和echarts图片 生成 word 前端解决方案
编程就像搭积木,少了任何一个就拼接不起来,所有积木都找到就只剩下调试. 一.echarts 获取图片方法getDataURL 详细配置:https://www.echartsjs.com/zh/a ...
- 迁移生产环境的GItLab11.3.5到新的服务器
在新的服务器上 rpm安装git 首先停止,Gitlab服务 root@localhost # gitlab-ctl stop 参考了 以下链接: https://blog.csdn.net/liul ...
- selenium中三大窗口切换
我们在做UI自动化时,不得不会遇到一些窗口跳转与弹框,在这种的时候如果不进行切换的话,继续执行脚本必然会报错,所以我们就需要用到切换窗口的方法. selenium中主要是三种窗口 Windows窗口 ...
- vue - 过滤器-钩子函数路由
一.关于路由 1.使用vue router 本质上是声明一种可以通过路径进行 挂子,用子 找到对应的 template 进行页面渲染 <!DOCTYPE html> <html la ...
- 201671010447 杨露露 实验十四 团队项目评审&课程学习总结
项目 内容 这个作业属于哪个课程 2016计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 实验十四 团队项目评审&课程学习总结 作业学习目标 总结这学期软件工程学习获得 一 ...