MST
星途 面试题库

面试题:C++虚函数表在多重继承下的特性

在C++的多重继承场景下,一个派生类从多个基类继承虚函数。请详细阐述虚函数表在这种情况下的布局和工作机制,以及不同基类虚函数表之间的关系。同时,说明在多重继承下,对象的虚函数调用过程与单一继承有何不同。
12.9万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

虚函数表布局和工作机制

  1. 单一继承时虚函数表布局
    • 在单一继承中,当一个类包含虚函数时,会生成一个虚函数表(vtable)。对象内部会有一个虚指针(vptr),指向这个虚函数表。虚函数表是一个函数指针数组,数组中的每个元素对应一个虚函数的地址。
    • 例如,有基类Base包含虚函数virtual void func1(),派生类Derived:public Base重写了func1Base对象的vptr指向Base类的虚函数表,其中func1的地址是Base::func1的地址。Derived对象的vptr同样指向Derived类的虚函数表,此时func1的地址被替换为Derived::func1的地址。
  2. 多重继承时虚函数表布局
    • 在多重继承下,派生类会从每个基类继承各自的虚函数表。假设有派生类DerivedBase1Base2多重继承,且Base1Base2都有虚函数。
    • Derived对象内部会有多个虚指针,分别指向不同基类的虚函数表。例如,Derived对象中可能先有一个vptr1指向Base1风格的虚函数表,然后有一个vptr2指向Base2风格的虚函数表。
    • 虚函数表中的函数指针排列顺序遵循一定规则。对于从某个基类继承来的虚函数,其在对应基类虚函数表中的位置与在该基类单独存在时虚函数表中的位置一致。如果派生类重写了某个基类的虚函数,那么在对应基类虚函数表中该虚函数位置处会替换为派生类重写版本的函数地址。

不同基类虚函数表之间的关系

  1. 相互独立:不同基类的虚函数表相互独立,它们之间没有直接的指针关联。每个虚函数表维护自己基类体系下的虚函数地址信息。
  2. 派生类关联:派生类通过多个虚指针分别与不同基类的虚函数表建立联系。派生类对象在内存中的布局包含多个虚指针,每个虚指针指向对应的基类虚函数表,使得派生类可以通过这些虚函数表调用不同基类的虚函数。

多重继承下虚函数调用过程与单一继承的不同

  1. 单一继承虚函数调用
    • 在单一继承中,通过对象的虚指针找到虚函数表,然后根据虚函数在虚函数表中的索引找到对应的函数地址并调用。例如,Base *ptr = new Derived(); ptr->func1();ptr指向Derived对象,通过Derived对象的vptr找到Derived类的虚函数表,再根据func1在虚函数表中的索引调用Derived::func1(如果Derived重写了func1)。
  2. 多重继承虚函数调用
    • 在多重继承下,调用虚函数时首先要确定从哪个基类视角调用。例如,Base1 *ptr1 = new Derived(); ptr1->func1();,这里ptr1Base1指针,通过Derived对象中指向Base1虚函数表的虚指针找到Base1风格的虚函数表,然后根据func1在该虚函数表中的索引调用相应函数。如果Derived重写了Base1func1,则调用Derived::func1
    • 而对于Base2 *ptr2 = new Derived(); ptr2->func2();(假设func2Base2的虚函数),则通过Derived对象中指向Base2虚函数表的虚指针找到Base2风格的虚函数表并调用相应函数。多重继承下需要根据不同的基类指针来确定使用哪个虚函数表进行虚函数调用,这与单一继承只使用一个虚函数表不同。