MST

星途 面试题库

面试题:C++ 多态实现中动态绑定机制的底层原理

描述 C++ 多态中动态绑定是如何实现的,涉及到哪些底层数据结构(如虚函数表等),并且说明这些数据结构在程序运行时是如何协同工作以实现动态绑定的。
22.6万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

动态绑定的实现方式

在C++ 中,动态绑定是通过虚函数和指针或引用实现的。当通过指针或引用调用虚函数时,C++ 运行时系统会在运行时根据对象的实际类型来决定调用哪个函数版本,而不是根据指针或引用的静态类型。

涉及的底层数据结构

  1. 虚函数表(Virtual Table,vtable):每个包含虚函数的类都有一个虚函数表。虚函数表是一个数组,其中存储了该类所有虚函数的地址。如果一个类从基类继承了虚函数,虚函数表中相应的条目会指向被覆盖的虚函数(如果有),否则指向基类的虚函数。
  2. 虚函数表指针(vptr):每个包含虚函数的对象都有一个虚函数表指针。这个指针指向该对象所属类的虚函数表。通常,vptr 被放置在对象内存布局的开头位置。

数据结构的协同工作

  1. 编译期:编译器为每个包含虚函数的类生成虚函数表,并在对象的构造函数中初始化 vptr,使其指向该类的虚函数表。
  2. 运行期:当通过指针或引用调用虚函数时,运行时系统首先通过对象的 vptr 找到对应的虚函数表。然后,根据虚函数在虚函数表中的索引,找到要调用的实际函数的地址,并执行该函数。

例如,假设有如下继承体系:

class Base {
public:
    virtual void foo() {
        std::cout << "Base::foo" << std::endl;
    }
};

class Derived : public Base {
public:
    void foo() override {
        std::cout << "Derived::foo" << std::endl;
    }
};

main 函数中:

int main() {
    Base* basePtr = new Derived();
    basePtr->foo(); // 动态绑定,调用 Derived::foo
    delete basePtr;
    return 0;
}

在上述代码中,basePtrBase* 类型,但实际指向 Derived 对象。当调用 basePtr->foo() 时,运行时系统通过 basePtr 所指向对象的 vptr 找到 Derived 类的虚函数表,进而调用 Derived::foo