C++,为什么 Base class 需要一个 VTable

C++ , Why Base class needs a VTable

根据我的理解,VTable 是调用函数的最派生版本所必需的。它将包含有关函数的最派生版本的条目......我的疑问是为什么我们需要为基础 class 创建一个 VTable。因为使用基础对象进行调用总是需要调用基础 class 函数。

当基 class 有一个或多个 virtual 成员函数时,基 class 构造函数将 VTable 分配给一个对象。

基本 class 构造函数无法知道正在构造的真实对象是基本 class 对象还是派生的 class 对象。

示例:

struct Base
{
    Base() {} 
    virtual ~Base() {}
};

struct Derived : public Base
{
    Derived() : Base() {}
    ~Derived() {}
};

void foo()
{
    Base b;
    Derived d;
}

Base::Base() 直接在行

中被调用
    Base b;

它通过

行中的 Derived::Derived() 间接调用
    Derived d;

Base 的实现如何知道 Base::Base() 是直接为 Base 调用还是间接为 Derived 调用?如果没有这些知识,它必须确保它的行为对它们都有效——这意味着为它们都设置 VTable。

因为 R Shau 不喜欢我的编辑,所以我提供了高度基于他的答案。

VTable 是一种处理多态性的方法。虽然 VTable 是 C++ 编译器广泛使用的技术,但它们可以自由提供任何其他解决方案。

当基 class 有一个或多个 virtual 成员函数时,基 class 构造函数将 VTable 分配给一个对象。

基 class 构造函数无法知道正在构造的真实对象是基 class 对象还是派生 class 对象,因此基对象必须保持指向指向有效的 VTable。

示例:

struct Base
{
    Base() {} 

    virtual void m() {}

    virtual ~Base() {}
};

struct Derived : public Base
{
    Derived() : Base() {}

    void m() override {}

    ~Derived() override {}
};

void foo()
{
    Base b;
    Derived d;

    Base * bPtr;
}

bPtr 可能指向 Base

    bPtr = & b;
    bPtr->m();

Derived

    bPtr = & d;
    bPtr->m();

由于 bPtrBase * 类型,如何执行多态调用 bPtr->m(),如果 bPtr 指向 [,则应该调用 Base::m() =23=] 和 Derived::m() 如果 bPtr 指向 d?答:在VTable中查找m()方法的地址。

解析 bPtr->m() 时会发生这样的事情:

   bPtr pointing to Base object
   bPtr-> vtable_pointer -> VTable of Base -> m() -> points to address of Base::m()
   
   bPtr pointing to Derived object
   bPtr-> vtable_pointer -> VTable of Derived -> m() -> points to address of Derived::m()

因此,如果基 class 中没有 VTable,则无法执行多态调用,因为在运行时不知道 bPtr 指向的对象是否真的是基 class 对象或派生 class 对象。