面试题答案
一键面试虚函数表工作原理
- 概念:虚函数表(vtable)是一个存储类的虚函数指针的数组。每个包含虚函数的类或从包含虚函数的类派生的类都有一个对应的虚函数表。
- 生成时机:当编译器遇到一个包含虚函数的类时,它会为这个类创建一个虚函数表。在编译期,编译器就确定了虚函数表的内容和布局。
- 运行时作用:在运行时,每个对象内部都会有一个隐藏的指针(通常称为vptr,虚函数表指针),该指针指向该对象所属类的虚函数表。当通过基类指针或引用调用虚函数时,程序会根据对象的vptr找到对应的虚函数表,然后在虚函数表中查找并调用适当的函数。
在实现动态多态中的作用
- 实现多态基础:动态多态允许通过基类指针或引用调用派生类中重写的虚函数。虚函数表为实现这种行为提供了一种机制,它使得程序在运行时能够根据对象的实际类型来决定调用哪个函数版本。
- 运行时绑定:由于虚函数表是在运行时通过对象的vptr访问的,所以函数调用能够基于对象的实际类型进行绑定,而不是基于指针或引用的静态类型,从而实现运行时的动态多态。
继承体系中虚函数表布局和变化
- 基类虚函数表布局:基类的虚函数表按照虚函数声明的顺序,将虚函数的地址依次放入表中。如果基类有多个虚函数,那么虚函数表中就会有对应数量的函数指针。
- 派生类虚函数表布局:
- 完全重写情况:如果派生类完全重写了基类的所有虚函数,派生类的虚函数表中的指针将指向派生类自己的虚函数实现。布局顺序与基类虚函数表一致,即按照基类虚函数声明顺序排列。
- 部分重写情况:当派生类部分重写基类虚函数时,对于重写的虚函数,虚函数表中的指针指向派生类的实现;对于未重写的虚函数,指针仍然指向基类的虚函数实现。布局依然按照基类虚函数声明顺序,重写的函数指针替换掉基类对应虚函数指针,未重写的保持基类虚函数指针。
- 新增虚函数情况:如果派生类新增了自己的虚函数,这些虚函数指针会追加在虚函数表的末尾。