Virtual
Virtual 作用: 允许在派生类中重新定义与基类同名函数并且可以通过其类的指针或引用来访问基类何派生类的同名函数。
1. 概述
简单地说,每一个含有虚函数(无论是其本身的,还是继承而来的)的类都至少有一个与之对应的虚函数表,其中存放着该类所有的虚函数对应的函数指针。例:
其中:
• B的虚函数表中存放着B::foo和B::bar两个函数指针。
• D的虚函数表中存放的既有继承自B的虚函数B::foo,又有重写(override)了基类虚函数B::bar的D::bar,还有新增的虚函数D::quz。
提示:为了描述方便,本文在探讨对象内存布局时,将忽略内存对齐对布局的影响。
2. 虚函数表构造过程
从编译器的角度来说,B的虚函数表很好构造,D的虚函数表构造过程相对复杂。下面给出了构造D的虚函数表的一种方式(仅供参考):
提示:该过程是由编译器完成的,因此也可以说:虚函数替换过程发生在编译时。
3. 虚函数调用过程
以下面的程序为例:
编译器只知道pb是B*类型的指针,并不知道它指向的具体对象类型 :pb可能指向的是B的对象,也可能指向的是D的对象。
但对于“pb->bar()”,编译时能够确定的是:此处operator->的另一个参数是B::bar(因为pb是B*类型的,编译器认为bar是B::bar),而B::bar和D::bar在各自虚函数表中的偏移位置是相等的。
无论pb指向哪种类型的对象,只要能够确定被调函数在虚函数中的偏移值,待运行时,能够确定具体类型,并能找到相应vptr了,就能找出真正应该调用的函数。
提示:本人曾在“C/C++杂记:深入理解数据成员指针、函数成员指针”一文中提到:虚函数指针中的ptr部分为虚函数表中的偏移值(以字节为单位)加1。
B::bar是一个虚函数指针, 它的ptr部分内容为9,它在B的虚函数表中的偏移值为8(8+1=9)。
当程序执行到“pb->bar()”时,已经能够判断pb指向的具体类型了:
• 如果pb指向B的对象,可以获取到B对象的vptr,加上偏移值8((char*)vptr + 8),可以找到B::bar。
• 如果pb指向D的对象,可以获取到D对象的vptr,加上偏移值8((char*)vptr + 8) ,可以找到D::bar。
• 如果pb指向其它类型对象...同理...
4. 多重继承
当一个类继承多个类,且多个基类都有虚函数时,子类对象中将包含多个虚函数表的指针(即多个vptr),例:
Virtual的更多相关文章
- Virtual Box配置CentOS7网络(图文教程)
之前很多次安装CentOS7虚拟机,每次配置网络在网上找教程,今天总结一下,全图文配置,方便以后查看. Virtual Box可选的网络接入方式包括: NAT 网络地址转换模式(NAT,Network ...
- 窥探Vue.js 2.0 - Virtual DOM到底是个什么鬼?
引言 你可能听说在Vue.js 2.0已经发布,并且在其中新添加如了一些新功能.其中一个功能就是"Virtual DOM". Virtual DOM是什么 在之前,React和Em ...
- VR ( Virtual Reality )、AR(Augmented Reality)、MR(Mix Reality)和CR(Cinematic Reality)是什么鬼?
整个社会对虚拟现实的研究和开发源于上个世纪六十年代,计算机图形学.人机接口技术.图像处理与模式识别.多传感技术.语音处理与音响技术.高性能计算机系统.人工智能等领域在之后半个世纪取得了长足的发展为虚拟 ...
- C#中Abstract和Virtual的区别
c# 中 Abstract和Virtual比较容易混淆,都与继承有关,并且涉及override的使用.下面讨论一下二者的区别: 一.Virtual方法(虚方法) virtual 关键字用于在基类中修饰 ...
- Java/C++之 public、protected、private ; virtual & abstract
一.绪 Java/C++都是面向对象的第三代计算机高级编程语言,其本质雷同,而语法确有差异,稍不注意容易引起混淆.本文总结了一些这两门语言的差异之处,仅供参考. 二.C++ 对于C++这门语言,就其类 ...
- 初识virtual memory
一.先谈几个重要的东西 virtual memory是一个抽象概念,书上的原文是"an abstraction of main memory known as virtual memory& ...
- php编译 :virtual memory exhausted: Cannot allocate memory
有时候用vps建站时需要通过编译的方式来安装主机控制面板.对于大内存的VPS来说一般问题不大,但是对于小内存,比如512MB内存的VPS来说,很有可能会出现问题,因为编译过程是一个内存消耗较大的动作. ...
- Delphi之静态方法,虚方法virtual,动态dynamic,抽象abstract,消息
Delphi之静态方法,虚方法virtual,动态dynamic,抽象abstract,消息 http://www.cnblogs.com/zhwx/archive/2012/08/28/266055 ...
- 转: Delphi的OverRide、OverLoad和Virtual方法
http://blog.csdn.net/ckli/article/details/2201418 override 重写 也叫覆盖 .方法的重写Overriding和重载Overloading是Ja ...
- C++: Virtual Table and Shared Memory
See at: 补充栏3: C++对象和共享内存 (叙述内容和Link1的内容基本一致) <C++网络编程 卷1:运用ACE和模式消除复杂性> <C++ Network Progra ...
随机推荐
- Manacher’s Algorithm (神啊)
(转载自)http://blog.csdn.net/hopeztm/article/details/7932245 这里描述了一个叫Manacher’s Algorithm的算法. 算法首先将输入字符 ...
- 1042 数字0-9的数量 1050 循环数组最大子段和 1062 序列中最大的数 1067 Bash游戏 V2 1092 回文字符串
1042 数字0-9的数量 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 给出一段区间a-b,统计这个区间内0-9出现的次数. 比如 10-19,1出现11次 ...
- WinForm事件中的Object sender和EventArgs e参数
Windows程序有一个事件机制.用于处理用户事件. 在WinForm中我们经常需要给控件添加事件.例如给一个Button按钮添加一个Click点击事件.给TextBox文本框添加一个KeyPress ...
- 【笔记】如何查看HTTP请求头&&【实验吧】天下武功唯快不破
打开Chrome浏览器,点击右上角“三”按钮. 点击工具-----再点击开发者工具 找到Network选项框.以百度经验页面为例,点击任务选框来查看网络请求流 在Network框内会有所有的请 ...
- LCT学习笔记
最近自学了一下LCT(Link-Cut-Tree),参考了Saramanda及Yang_Zhe等众多大神的论文博客,对LCT有了一个初步的认识,LCT是一种动态树,可以处理动态问题的算法.对于树分治中 ...
- HDU3336 Count the string
居然一A了,说明对朴素的KMP还是有一定理解. 主要就是要知道next数组的作用,然后就可以计算每个i结尾的满足题意的串个数. #include<cstdio> #include<c ...
- javascript 三种弹出对话框
第一种:alert()方法 第二种:confirm()方法 返回一个布尔值,根据返回的值可以执行相应操作. 第三种: prompt()方法 返回输入的消息,或者其默认值提示框经常用于提示用户在进入页面 ...
- UWP 手绘视频创作工具技术分享系列 - 位图的绘制
前面我们针对 SVG 的解析和绘制做了介绍,SVG 是图片的一种形式,而另一种很重要的图片是:位图,包括 png.jpeg.bmp 等格式.位图的基本规则是,组成的基本元素是像素点,由宽度 * 高度个 ...
- 初学python之,IDLE安装
首先新手上路,写的第一篇博客,希望大家不要吐槽. 1.首先在python官网下载最新python版本 https://www.python.org/(注意根据自己的操作系统来选版本) 安装很简单傻瓜式 ...
- ES6的Iterator遍历器
JS表示集合的对象主要有Array.Set.Object.Map,在以前,遍历它们需要使用2种不同的方法,而现在,JS提出了Iterator机制,可以给不同的数据结构提供统一的遍历方法,就是for…o ...