1.概述

  • 每一个含有虚函数(无论是其本身就含有的,还是从基类继承过来的)的类都至少有一个与之对应的虚函数表,其中存放着该类所有的虚函数对应的函数指针。如下图所示


    其中:

    • B的虚函数表中存放着B::foo和B::bar两个函数指针
    • D的虚函数表中存放的既有继承自B的虚函数B::foo,又有重写了基类虚函数B::bar的D::bar,还有新增的虚函数D::quz。

2.虚函数表的构造过程

  • 从编译器的角度来说,B的虚函数表很好构造,D的虚函数表构造过程相对复杂,下面给出了构造D的虚函数表的一种方式,该过程是由编译器完成的,即虚函数替换过程发生在编译时:

3.虚函数的调用过程

  • 以下面的程序为例:
  • 编译器只知道pb是B*类型的指针,并不知道它指向的具体对象类型,pb可能指向的是B的对象,也有可能指向的是D的对象。但对于pb->bar(),编译时能确定的是:此处->的另一个参数是B::bar(因为pb是B*类型的,编译器认为bar是B::bar),而B::bar和D::bar在各自虚函数表中的偏移位置是相等的。无论pb指向哪种类型的对象,只要能够确定被调函数在虚函数表的偏移值,等到运行时能够确定具体类型,并能找到相应的vptr,这样就能找出真正应该调用的函数。由于虚函数指针中的ptr部分为虚函数表中的偏移值(以字节为单位)+1,所以B::bar是一个虚函数指针,它的ptr部分内容是9,它在B的虚函数表中的偏移值为8。当程序执行到pb->bar()时,已经能够判断pb指向的具体类型了:
    • a.如果pb指向B的对象,可以获取到B对象的vptr,加上偏移值8(char(*)vptr + 8),可以找到B::bar
    • b.如果pb指向的是D的对象,可以获取D的对象vptr,加上偏移值8(char(*)vptr + 8),可以找到D::bar

3.多重继承

  • 当一个类继承多个类,且多个基类都有虚函数时,子类对象中将包含多个虚函数表中的指针(即多个vptr),如下所示:
  • 其中:D的自身虚函数与B基类共用了同一个虚函数表,因此称B为D的主基类。虚函数替换过程与前面描述类似,只是多了一个虚函数表,多了一次拷贝和替换的过程。虚函数的调用过程,与前面基本类似,区别在于基类指针指向的位置可能不是派生类对象的起始位置,如下面的程序所示:

4.博客原文

  • 博客原文

虚函数实现的基本原理(转载)相关推荐

  1. 【学习笔记】C++ 中的 virtual 关键字与虚函数

    目录 先决条件 前言 演示示例 virtual 关键字的作用 虚函数的规则 参考与拓展 深入拓展 先决条件 了解 C++ 中的多态这个概念. 前言 virtual 关键字是面对对象中,用于修饰类中的成 ...

  2. C/C++杂记:虚函数的实现的基本原理 虚函数表

    Malecrab 博客园 首页 新随笔 联系 订阅 管理 C/C++杂记:虚函数的实现的基本原理 1. 概述 简单地说,每一个含有虚函数(无论是其本身的,还是继承而来的)的类都至少有一个与之对应的虚函 ...

  3. C++中重载与重写函数区别及虚函数(转载)

    C++中重载与重写函数区别及虚函数 C++中的虚函数(virtual function) 1.简介 虚函数是C++中用于实现多态(polymorphism)的机制.核心理念就是通过基类访问派生类定义的 ...

  4. 构造函数为什么不能是虚函数 ( 转载自C/C++程序员之家)

    从存储空间角度,虚函数对应一个指向vtable虚函数表的指针,这大家都知道,可是这个指向vtable的指针其实是存储在对象的内存空间的.问题出来了,如果构造函数是虚的,就需要通过 vtable来调用, ...

  5. 【转载】什么是C++虚函数、虚函数的作用和使用方法

    我们知道,在同一类中是不能定义两个名字相同.参数个数和类型都相同的函数的,否则就是"重复定义".但是在类的继承层次结构中,在不同的层次中可以出现名字相同.参数个数和类型都相同而功能 ...

  6. 转载:(C++)浅谈多态基类析构函数声明为虚函数

    原博文:https://www.cnblogs.com/AndyJee/p/4575810.html 主要内容: 1.C++类继承中的构造函数和析构函数 2.C++多态性中的静态绑定和动态绑定 3.C ...

  7. (转载)虚函数的工作原理

    转载请标明出处,原文地址:http://blog.csdn.net/hackbuteer1/article/details/7883531 一.虚函数的工作原理       虚函数的实现要求对象携带额 ...

  8. C++中的虚函数(virtual function)

    1回顶部 一.简介 虚函数是C++中用于实现多态(polymorphism)的机制.核心理念就是通过基类访问派生类定义的函数.假设我们有下面的类层次: class A { public: virtua ...

  9. 一口气搞懂《虚函数和纯虚函数》

    学习C++的多态性,你必然听过虚函数的概念,你必然知道有关她的种种语法,但你未必了解她为什么要那样做,未必了解她种种行为背后的所思所想.深知你不想在流于表面语法上的蜻蜓点水似是而非,今天我们就一起来揭 ...

最新文章

  1. 牛客题霸 NC4 判断链表中是否有环
  2. Struts2的核心过滤器
  3. 为什么需要实现幂等性?
  4. ES6之路第十三篇:Iterator和for...of循环
  5. 爱因斯坦谈教育,放在首位的该是什么?
  6. 傲游浏览器记事本怎么打开
  7. [CF671E] Organizing a Race
  8. 清华计算机系山东分数,清华大学山东录取分数线|2021清华大学山东分数线|2021年清华大学山东高考分数线|2021年清华大学山东招生计划录取人数...
  9. jQuery 属性操作 - addClass() 和 removeClass() 方法
  10. 搭建GOOGLE企业邮箱以及域名解析全攻略
  11. 记录deecamp2018之旅
  12. arduino 控制无刷电机_怎样使用Arduino控制无刷电机
  13. 使用PEG估值法简单选股(1)
  14. Windows易升升级指南(解决大版本间更新95%的问题)
  15. linux 下载百度网盘资源 centos安装aria2
  16. Windows上的Oracle检查列表。 (文档ID 443813.1)
  17. Vue实现点击上传图片预览图片功能
  18. PicGo+Gitee(码云)搭建个人博客的免费图床
  19. Flutter之路由与导航
  20. LEETCODE-刷题个人笔记 Python(1-400)-TAG标签版本

热门文章

  1. 【译】Swift算法俱乐部-查找最大/最小值
  2. 如何快速的vue init 属于自己的vue模板?
  3. Mysql中分页查询两个方法比较
  4. 云服务器 ECS 配置:阿里云ECS Windows Server 2012 搭建AD
  5. ionic中使用Cordova Uglify 压缩js与css
  6. PLSQL连Oracle数据库Could not load ……\bin\oci.dll
  7. 网络工程与机房等精华指引贴
  8. 9月29日,访问量4200,留个脚印
  9. “远征记”——从燕郊骑自行车回京
  10. 腾讯二面:Redis 事务支持 ACID 么?