面试题答案
一键面试- 编译器阶段:
- 当编译器看到
Base* ptr = new Derived();
时,它会为Base
和Derived
类分别构建虚函数表(vtable)。在Base
类的虚函数表中,会有func
函数的地址,这里是Base::func
的地址(因为它是虚函数,需要通过虚函数表来调用)。 - 对于
Derived
类,编译器会检查其对基类虚函数的重写情况。由于Derived
重写了func
函数,在Derived
类的虚函数表中,对应func
函数的条目会被替换为Derived::func
的地址。 - 当执行
Base* ptr = new Derived();
时,编译器会为Derived
对象分配内存,在对象的内存布局中,对象的首地址处会存放一个指针,该指针指向Derived
类的虚函数表(vtable)。
- 当编译器看到
- 运行时阶段:
- 当执行
ptr->func();
时,运行时系统首先会根据ptr
所指向对象的首地址,找到其虚函数表指针。由于ptr
指向的是Derived
类对象,所以这个虚函数表指针指向Derived
类的虚函数表。 - 然后,运行时系统在虚函数表中查找
func
函数对应的条目,因为是Derived
类的虚函数表,这里找到的是Derived::func
的地址。 - 最后,运行时系统通过找到的
Derived::func
的地址调用该函数,从而实现了多态性。
- 当执行
- 虚函数表(vtable)的作用:
- 实现多态性:虚函数表为运行时系统提供了一种机制,通过对象的虚函数表指针,运行时系统能够在运行时动态地确定应该调用哪个函数版本。对于不同类型的对象(如
Base
对象和Derived
对象),即使通过基类指针来操作,也能根据对象实际类型对应的虚函数表找到正确的虚函数实现。 - 存储虚函数地址:虚函数表存储了类中所有虚函数的地址。在类的继承体系中,每个类都有自己的虚函数表,它记录了该类及其基类虚函数在该类中的实现地址,使得运行时系统能够高效地进行函数调用的动态绑定。
- 实现多态性:虚函数表为运行时系统提供了一种机制,通过对象的虚函数表指针,运行时系统能够在运行时动态地确定应该调用哪个函数版本。对于不同类型的对象(如