虚函数

虚函数的工作原理

虚函数的实现要求对象携带额外的信息,这些信息用于确定运行时调用哪一个虚函数,这一信息具有一种被称为虚函数表指针(vptr)的指针形式。vptr指向一个被称为虚函数表(vtbl)的函数指针数组,每一个包含虚函数的类都关联到一个vtbl。当一个对象调用了一个虚函数,实际被调用的虚函数通过以下步骤确定:找到对象的vptr指向的vtbl,在vtbl中找到对应的函数指针。

虚函数的地址翻译取决于对象的内存地址,而不取决于数据类型(编译器对函数调用的合法性检查依赖于数据类型)。如果一个类包含了虚函数,类及其派生类就会生成一张虚函数表vtable,在类对象地址空间中存储一个该虚函数表的入口,这个入口时构造对象时编译器自动写入的。由于虚函数对象的内存空间包含虚函数表的入口,编译器能通过该入口调用正确的虚函数,因此这个函数的地址就不再由数据类型决定了。对于一个父类对象指针调用虚函数,如果赋父类对象的指针,就调用父类的虚函数;若赋子类对象的指针,就会调用子类的函数。

每当创建一个包含虚函数的类或者从包含虚函数的类中派生的类时,编译器会对该类生成一个虚函数表保存类中所有虚函数的地址,可以将这个虚函数表看成一个函数指针数组。在带有虚函数的类中,编译器会秘密置入一个VPTR,指向这个对象的VTABLE,当构造该派生类对象时,VPTR被初始化指向该派生类的VTABLE。可以认为VTABLE是该类所有对象共有的;而VPTR则是每个类对象独一份的,且在该类对象被构造时被初始化。

通过基类指针做虚函数调用(多态调用)时,编译器静态的插入取得VPTR,并在VTABLE中选取正确的虚函数。

每个类有一个VTABLE,并且该虚函数表对该类的所有实例共享,但类的每个实例都只有一个VPTR。

参考链接:

  1. C++中虚函数工作原理和(虚)继承类的内存占用大小计算

C++面试常见问题——12虚函数的更多相关文章

  1. 【C++面试】关于虚函数的常见问题

    1.虚函数的代价 1)带有虚函数的每个类会产生一个虚函数表,用来存储虚成员函数的指针 2)带有虚函数的每个类都会有一个指向虚函数表的指针 3)不再是内敛函数,因为内敛函数可以在编译阶段进行替代,而虚函 ...

  2. C++语言基础(12)-虚函数

    一.虚函数使用的注意事项 1.只需要在虚函数的声明处加上 virtual 关键字,函数定义处可以加也可以不加. 2.为了方便,你可以只将基类中的函数声明为虚函数,这样所有子类中具有遮蔽(覆盖)关系的同 ...

  3. 【校招面试 之 C/C++】第11题 C++ 纯虚函数

    1.纯虚函数 成员函数的形参后面写上=0,则成员函数为纯虚函数. 纯虚函数声明: virtual 函数类型 函数名 (参数表列) = 0: class Person { virtual void Di ...

  4. 【校招面试 之 C/C++】第10题 C++不在构造函数和析构函数中调用虚函数

    1.不要在构造函数中调用虚函数的原因 在概念上,构造函数的工作是为对象进行初始化.在构造函数完成之前,被构造的对象被认为“未完全生成”.当创建某个派生类的对象时,如果在它的基类的构造函数中调用虚函数, ...

  5. 以boost::function和boost:bind取代虚函数

    转自:http://blog.csdn.net/Solstice/archive/2008/10/13/3066268.aspx 这是一篇比较情绪化的blog,中心思想是“继承就像一条贼船,上去就下不 ...

  6. python 常忘代码查询 和autohotkey补括号脚本和一些笔记和面试常见问题

    笔试一些注意点: --,23点43 今天做的京东笔试题目: 编程题目一定要先写变量取None的情况.今天就是因为没有写这个边界条件所以程序一直不对.以后要注意!!!!!!!!!!!!!!!!!!!!! ...

  7. C++ 复习要点、面试常见问题总结

    本文总结一下C++面试时常遇到的问题.C++面试中,主要涉及的考点有: 关键字极其用法,常考的关键字有const, sizeof, typedef, inline, static, extern, n ...

  8. 为何JAVA虚函数(虚方法)会造成父类可以"访问"子类的假象?

      首先,来看一个简单的JAVA类,Base. 1 public class Base { 2 String str = "Base string"; 3 protected vo ...

  9. C++之虚函数的作用和使用方法

    在同一类中是不能定义两个名字相同.参数个数和类型都相同的函数的,否则就是“重复定义”.但是在类的继承层次结构中,在不同的层次中可以出现名字相同.参数个数和类型都相同而功能不同的函数.例如在例12.1( ...

随机推荐

  1. 02使用GitHub远程仓库

    一.远程库配置 由于本地的GIT仓库和GitHub仓库之间的传输是通过SSH加密的,所以需要以下配置: 1.创建SSH key 为什么GitHub需要SSHKey:根据key来授权,有哪些key可以往 ...

  2. POJ 2104 主席树模板题

    #include <iostream> #include <cstdio> #include <algorithm> int const maxn = 200010 ...

  3. C# 读取和写入txt文件

    读取: 1.使用StreamReader读取文件,然后一行一行的输出 StreamReader sr = new StreamReader(path,Encoding.Default); String ...

  4. IDEA下的SVN设置以及TortoiseSVN安装后bin目录下没有svn.exe如何解决?

    1.首先,我们要确保电脑上已经安装了TortoiseSVN. 2.打开IDEA-File-Settings-Version Control-Subversion,在右边的界面上选择TortoiseSv ...

  5. mybatis 查询标签

    语法 参考:http://www.mybatis.org/mybatis-3/zh/dynamic-sql.html <![CDATA[内容]]>: 参考: http://blog.csd ...

  6. [Android实例] Android网络收音机项目(内含源码)

    ======================帖子内容===================================最近喜欢听广播,但是搜索了一下,苦于网上没有Android的网络收音机项目的例 ...

  7. Android游戏开发学习(5)--实现Button悬浮于与SurfaceView之上

    原文:http://daikainan.iteye.com/blog/1407355 实现Button悬浮于与SurfaceView之上实现 先看效果: 注意:你实现的SurfaceView和andr ...

  8. 任意promise串行执行算法 - 童彪

      // 任意promise串行执行算法 - 童彪 function runAllPromise() { var p1 = new Promise((resove, reject) => { s ...

  9. Python - 列表与字符串的相互转换

    1. 列表转换成字符串,用''.join() # 创建一个列表 list1 = ['a','b','c'] # 将列表的元素拼接为字符串 print(''.join(list1)) # 将列表的元素通 ...

  10. C++11并发编程4------线程间共享数据

    举个例子: 刚参加工作的你,只能租房住,嫌房租贵就和别人合租了,两个人住一起只有一个洗手间,每天早上起床的时候,如果你室友在洗手间,你就只能等着,如果你强行进去,那画面就不可描述了.同样的问题,如果多 ...