Calling a virtual function is slower than calling a non-virtual function for a couple of reasons: First, we have to use the *__vptr to get to the appropriate virtual table. Second, we have to index the virtual table to find the correct function to call. Only then can we call the function. As a result, we have to do 3 operations to find the function to call, as opposed to 2 operations for a normal indirect function call, or one operation for a direct function call. However, with modern computers, this added time is usually fairly insignificant.

Also as a reminder, any class that uses virtual functions has a __vptr, and thus each object of that class will be bigger by one pointer. Virtual functions are powerful, but they do have a performance cost.

https://www.learncpp.com/cpp-tutorial/125-the-virtual-table/

Because for virtual functions linking was not done at compile time. So, what happens when a call to virtual function is executed ,i.e.

Steps are as follows,

  • vpointer hidden in first 4 bytes of the object will be fetched
  • vTable of this class is accessed through the fetched vPointer
  • Now from the vTable corresponding function’s address will be fetched
  • Function will be executed from that function pointer

https://thispointer.com/how-virtual-functions-works-internally-using-vtable-and-vpointer/

A late-binding process involves the following activities:

1)Compiler adds a hidden vPtr member to the class, and generates one unique vtable for the class.

At compilation time, when compiler sees the definition of a class with virtual methods, it will build a virtual table (vtable) for the class, which is an array of function pointers to the implementations of all the virtual methods, and add a hidden data member vPtr to the class definition as the FIRST data member.

Now suppose the methods of classes in Fig. 1 (Hi, Hi1, Hi2, Hi3) are all virtual functions. The memory footprint of an object of class Derived becomes:

pDerived

pBase1             pBase2            pBase3

+----+-------------+-------+---------+-------+----------+----------+

|vptr|    a1    | vptr2 |   a2    | vptr3 |     a3   |     a    |

+----+-------------+-------+---------+-------+----------+----------+

0    4            104     108       208     212        312        412

Fig. 2.  Memory footprint of a polymorphic type object

As you can see in the memory footprint, if you use a Base2 pointer to receive a Derived object, for example, this pointer will point to memory offset 104 as pBase2 does.

Note that each Derive object will have its own memory footprint, with the same structure but in different memory locations. However, the vPtrs will all be pointing to the same method implementations, in other words, the vPtr2 of two instances will contain the same address.

The derived-class and the first base class shares the same vPtr, which points to their shared merged vtable (see following section “Inheritance of Base-class vPtrs” for details). The rest of the base classes have their own vPtrs.

Note that no matter how complicated the inheritance hierarchy is, a function pointer in the vtable always points to the latest/lowest implementation of the virtual function in the inheritance hierarchy.

2)Compiler generates code to do dynamic binding using the vtable.

At compilation time, when compiler sees a call to a virtual method thourgh a pointer (pBase2->Hi2( )), it knows that the address of the function is only known at run time, so it will not try to find the implementation of the function. Instead, it knows that the pointer (pBase2) will be pointing to a vPtr at run time. So it generates code to go through the vPtr to find the vtable (whose composition is already know from the type of the pointer), and go to a certain entry of that vtable, fatch that function pointer, and make the call.

3)At run time, when an object is created out of this class definition, its vPtr member will be assigned the address of the class’s vtable.

http://www.referencecode.org/2013/02/c-advanced-tutorial-vptr-and-vtable.html

c+多态的本质:编译器维护了类型信息同时插入了解释执行机制的更多相关文章

  1. 当我们有多个类 继承同一个父类 这时候使用多态时候 可以使用该父类的类型做引用 不需要将object做引用

    当我们有多个类 继承同一个父类 这时候使用多态时候 可以使用该父类的类型做引用 不需要将object做引用

  2. 初识JAVA(【面向对象】:pub/fri/pro/pri、封装/继承/多态、接口/抽象类、静态方法和抽象方法;泛型、垃圾回收机制、反射和RTTI)

    JAVA特点: 语法简单,学习容易 功能强大,适合各种应用开发:J2SE/J2ME/J2EE 面向对象,易扩展,易维护 容错机制好,在内存不够时仍能不崩溃.不死机 强大的网络应用功能 跨平台:JVM, ...

  3. Java编程思想学习笔记——类型信息

    前言 运行时类型信息(RTTI:Runtime Type Information)使得我们可以在程序运行时发现和使用类型信息. Java在运行时识别对象和类的信息的方式: (1)一种是RTTI,它假定 ...

  4. 《Java编程思想》笔记14.类型信息

    运行时类型信息使得你可以在运行时发现和使用类型信息,主要有两种方式: "传统的"RTTI,它假定我们在编译时已经知道了所有的类型: "反射"机制,它允许我们在运 ...

  5. Java类型信息(RTTI和反射)

    要想在IT领域站得住脚,必须得不断地学习来强化自己,但是学过的技术不实践很容易便被遗忘,所以一直都打算开个博客,来记录自己学的知识,另外也可以分享给有需要的人! 最近在学习反射,为了更好地理解反射,就 ...

  6. 【JavaSE】运行时类型信息(RTTI、反射)

    运行时类型信息使得你可以在程序运行时发现和使用类型信息.--<Think in java 4th> **** 通常我们在面向对象的程序设计中我们经常使用多态特性使得大部分代码尽可能地少了解 ...

  7. 你好,C++(4)2.1.3 我的父亲母亲:编译器和链接器 2.1.4 C++程序执行背后的故事

    2.1.3  我的父亲母亲:编译器和链接器 从表面上看,我是由Visual Studio创建的,而实际上,真正负责编译源代码创建生成可执行程序HelloWorld.exe的却是Visual Studi ...

  8. Java 编程思想 Chapter_14 类型信息

    本章内容绕不开一个名词:RTTI(Run-time Type Identification) 运行时期的类型识别 知乎上有人推断作者是从C++中引入这个概念的,反正也无所谓,理解并能串联本章知识才是最 ...

  9. 类型信息(RTTI和反射)——RTTI

    运行时类型信息可以让你在程序运行时发现和使用类型信息. 在Java中运行时识别对象和类的信息有两种方式:传统的RTTI,以及反射.下面就先来说下RTTI. 1.RTTI: RTTI:在运行时,识别一个 ...

随机推荐

  1. 把jar包安装到本地Maven仓库

    使用的场景 自己写的工具类想安装到本地 从Maven仓库中下载不下来的jar 使用的步骤       首先要保证自己的Maven配置全局环境变量,如果没有配置过maven全局变量,可以按照下面的步骤配 ...

  2. Scala Type Parameters 1

    类型参数 表现形式:在名称后面以方括号表示, Array[T] 何处使用 class 中,用于定义变量.入参.返回值 class Pair[T, S](val first: T, val second ...

  3. 『Broken Robot 后效性dp 高斯消元』

    Broken Robot Description 你作为礼物收到一个非常聪明的机器人走在矩形板上.不幸的是,你明白它已经破碎并且行为相当奇怪(随机).该板由N行和M列单元组成.机器人最初位于第i行和第 ...

  4. Linux中常用命令cat

    cat可谓是随处可用,全名:concatenate and print files.用于连接和打印文件,按序读取文件内容,然后输出到标准输出.如果文件是单个破折号-或者缺乏文件,cat将读取标准输入. ...

  5. python第五章程序练习题

    5.2 def isOdd(a): if a%2!=0: return True else: a=eval(input()) print(isOdd(a)) 5.3 def isNum(x): try ...

  6. opencv常用数据结构

    2019/10/29 1.Mat 成员函数:cols.rows.channels.ptr获取任意行的首地址.at处理像素 2.InputArray/OutArray相当于Mat 2019/11/4 1 ...

  7. 几分钟打造超级好看又好用的zsh command line环境

    source: https://www.pexels.com/photo/office-working-app-computer-97077/ 注:这篇适用于用MAC 开发的developer 身为程 ...

  8. WPF 在MVVM模式下弹出子窗体的方式

    主要是通过一个WindowManager管理类,在window后台代码中通过WindowManager注册需要弹出的窗体类型,在ViewModel通过WindowManager的Show方法,显示出来 ...

  9. Eclipse集成Git做团队开发:代码管理

    在日常开发工作中,我们通常使用版本控制软件管理团队的源代码,常用的SVN.Git.与SVN相比,Git有分支的概念,可以从主分支创建开发分支,在开发分支测试没有问题之后,再合并到主分支上去,从而避免了 ...

  10. Vue自定义组件中Props中接收数组或对象

    原文:https://www.jianshu.com/p/904551dc6c15 自定义弹框组件时,需要在弹框内展示商品list,所以需要组件中的对应字段接收一个Array数组,默认返回空数组[], ...