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. centos 7 下 rabbitmq 3.8.0 & erlang 22.1 源码编译安装

    centos 7 下 rabbitmq 3.8.0 & erlang 22.1 源码编译安装 安装前请检查好erlang和rabbitmq版本是否相匹配参考:RabbitMQ Erlang V ...

  2. OI之路

    由于各种因素 学习.初赛.时间... 我的oi可能会结束, 我也不甘于放弃, 所以 综合今后的表现, 我再决定 以后我尽量写博客.

  3. C++强大背后

    转自MiloYip大神的博客 [原文]http://www.cnblogs.com/miloyip/archive/2010/09/17/behind_cplusplus.html 在31年前(197 ...

  4. Java学习:数据库连接池技术

    本节内容 数据库连接池 Spring JDBC : JDBC Template 数据库连接池 1.概念:其实就是一个容器(集合),存放数据库连接的容器 当系统初始化好后,容器中会申请一些连接对象,当用 ...

  5. MyBatis系列(三) MyBatis 配置文件

    一.properties 此标签的主要作用是引用配置文件,以数据源来举例. 新建mybatis-confing.properties配置文件 mybatis-confing.properties dr ...

  6. Elasticsearch常见用法-分布式集群

    集群内部工作方式 Elasticsearch用于构建高可用和可扩展的系统.扩展的方式可以是购买更好的服务器(纵向扩展(vertical scale or scaling up))或者购买更多的服务器( ...

  7. MySQL远程连接ERROR 2003 (HY000):Can't connect to MySQL server on'XXXXX'(111) 的问题

    装了个navicat ,然后去连接mysql服务器,一直连不上,一开始以为是防火墙问题,后来防火墙都关闭, iptable服务关闭,还是不行,网上查了下:主要是因为设置了bind_address=12 ...

  8. 象棋中“车”的攻击范围_C#

    如题: var a = new String[8,8]; int h, l; Console.WriteLine("输入车所在的行(0-7):"); h = int.Parse(C ...

  9. Python3字典与集合

    一.Python3字典 字典是另一种可变容器模型,且可存储任意类型对象字典的每个键值(key=>value)对用冒号":"分割,每个键值对之间用逗号"," ...

  10. Java自学-类和对象 传参

    Java中的传参 变量有两种类型 基本类型 和类类型 参数也是变量,所以传参分为 基本类型传参 类类型传参 步骤 1 : 基本类型传参 基本类型传参 在方法内,无法修改方法外的基本类型参数 publi ...