1.47、虚函数的底层原理是什么?

C++中虚函数的底层实现原理主要依赖于**虚函数表(vtable)和虚函数指针(vptr)**机制,用以实现运行时多态(动态绑定)。具体核心点如下:

虚函数表(vtable)

  • • 每个包含虚函数的类,编译器都会生成一张虚函数表,这是一张存放该类所有虚函数地址的函数指针数组。
  • • 虚函数表是类级别的静态数据,所有该类对象共享同一张虚函数表。
  • • 如果派生类重写了基类的虚函数,虚函数表中对应位置的指针会替换为派生类的函数地址。

虚函数指针(vptr)

  • • 每个含有虚函数的对象实例内部会隐式包含一个指向虚函数表的指针,称为vptr。
  • • vptr通常存放在对象内存的起始位置(编译器实现细节),用于在运行时定位该对象对应的虚函数表。

动态绑定过程

当通过基类指针或引用调用虚函数时,编译器生成的代码并不是直接调用某个固定函数地址,而是:

  1. 1. 通过对象的vptr找到对应的虚函数表。
  2. 2. 根据虚函数在表中的固定偏移,取出对应的函数指针。
  3. 3. 调用该函数指针指向的函数,实现动态多态调用。

这样,无论基类指针实际指向哪个派生类对象,调用的都是该派生类中重写的虚函数版本。

多继承和复杂情况

  • • 多重继承时,对象会包含多个vptr,分别指向各基类的虚函数表。
  • • 虚函数表的构造和维护由编译器负责,保证虚函数调用的正确性。
  • • 菱形继承等复杂继承结构下,虚继承机制会进一步调整vptr和虚函数表布局。

总结

  • • 虚函数表(vtable):存储虚函数地址的数组,实现函数地址的动态查找。
  • • 虚函数指针(vptr):对象内隐藏指针,指向虚函数表,实现运行时类型识别。
  • • 动态绑定:通过vptr和vtable实现基类指针调用派生类函数,保证多态性。

这种机制使C++能够在编译时静态类型确定的基础上,实现运行时的多态行为,是面向对象设计中多态性的关键技术。

简单示意图

对象内存布局:
+----------------+
| vptr --> vtable|
| 成员变量       |
+----------------+

vtable:
+--------------------+
| &Class::virtualFunc1|
| &Class::virtualFunc2|
| ...                |
+--------------------+

本文首发于【讳疾忌医-note】公众号,未经授权,不得转载。
(加入我的知识星球,免费获取账号,解锁所有文章。)

阅读剩余
THE END