美文网首页
C&C++ 虚函数实现的基本原理

C&C++ 虚函数实现的基本原理

作者: 深红的眼眸 | 来源:发表于2020-02-11 10:51 被阅读0次

本文根据众多互联网博客内容整理后形成,引用内容的版权归原始作者所有,仅限于学习研究使用,不得用于任何商业用途。

1. 概述

简单地说,每一个含有虚函数(无论是其本身的,还是继承而来的)的类都至少有一个与之对应的虚函数表,其中存放着该类所有的虚函数对应的函数指针。例:

image.png

其中:

  • B的虚函数表中存放着B::foo和B::bar两个函数指针。

  • D的虚函数表中存放的既有继承自B的虚函数B::foo,又有重写(override)了基类虚函数B::bar的D::bar,还有新增的虚函数D::quz。

提示:为了描述方便,本文在探讨对象内存布局时,将忽略内存对齐对布局的影响。

2. 虚函数表构造过程

从编译器的角度来说,B的虚函数表很好构造,D的虚函数表构造过程相对复杂。下面给出了构造D的虚函数表的一种方式(仅供参考):

image.png

提示:该过程是由编译器完成的,因此也可以说:虚函数替换过程发生在编译时。

3. 虚函数调用过程

以下面的程序为例:

image.png

编译器只知道pb是B*类型的指针,并不知道它指向的具体对象类型 :pb可能指向的是B的对象,也可能指向的是D的对象。

但对于“pb->bar()”,编译时能够确定的是:此处operator->的另一个参数是B::bar(因为pb是B*类型的,编译器认为bar是B::bar),而B::bar和D::bar在各自虚函数表中的偏移位置是相等的。

无论pb指向哪种类型的对象,只要能够确定被调函数在虚函数中的偏移值,待运行时,能够确定具体类型,并能找到相应vptr了,就能找出真正应该调用的函数。

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),例:

image.png

其中:D自身的虚函数与B基类共用了同一个虚函数表,因此也称B为D的主基类(primary base class)。

虚函数替换过程与前面描述类似,只是多了一个虚函数表,多了一次拷贝和替换的过程。

虚函数的调用过程,与前面描述基本类似,区别在于基类指针指向的位置可能不是派生类对象的起始位置,以如下面的程序为例:

[图片上传失败...(image-4d80cf-1581389064147)]

5. 菱形继承

本文不讨论菱形继承的情形,个人觉得:菱形继承的复杂度远大于它的使用价值,这也是C++让人又爱又恨的原因之一。

如果想要深入研究,可以参考:Itanium C++ ABI

参考文档
C/C++杂记:虚函数的实现的基本原理

相关文章

  • C&C++ 虚函数实现的基本原理

    本文根据众多互联网博客内容整理后形成,引用内容的版权归原始作者所有,仅限于学习研究使用,不得用于任何商业用途。 1...

  • C++ 虚函数

    C++ 虚函数 虚函数 基类中使用virtual关键字声明的函数,称为虚函数。虚函数的实现,通过虚函数表来实现的。...

  • 3.0 C++远征:虚函数与虚析构函数实现原理

    2-7虚函数与虚析构函数实现原理 [TOC] 1.虚函数的实现原理 (1)引入概念:函数指针。 ​ 指向函数的...

  • c++虚函数与虚表初步

    虚指针与虚表 虚表和虚函数是为了实现动态多态的机制,由编译器实现 当一个类本身定义了虚函数,或其父类有虚函数时,编...

  • C++ 虚函数表和虚函数指针机制

    虚函数的作用是实现派生类继承基类的接口和一个默认的实现 那么是如何实现这种机制的呢?答案:通过虚函数表和虚函数指针...

  • 多态

    virtual 关键字定义虚函数多态是通过指向虚函数表的虚指针实现的。 例子

  • 虚继承和虚函数

    虚继承和虚函数 虚继承和虚函数是毫不相关的两个概念,但是在实现上又有所类似;虚函数是C++中实现多态的一个重要手段...

  • C++面向对象

    小结 虚函数是virtual声明的。实现动态链接的功能。 纯虚函数是没有函数主体的虚函数。 一、C++继承 1.当...

  • 关于objc_runtime的消息机制(二)

    接上篇,我们已经大概的聊完了c++的虚函数实现机制。间接寻址体现在虚函数表的实现上。虚函数表由编译负责帮我们维护。...

  • C++虚函数表

    虚函数表 C++中虚函数是通过一张虚函数表(Virtual Table)来实现的,在这个表中,主要是一个类的虚函数...

网友评论

      本文标题:C&C++ 虚函数实现的基本原理

      本文链接:https://www.haomeiwen.com/subject/vjwtfhtx.html