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();
由于 bPtr
是 Base *
类型,如何执行多态调用 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 对象。
根据我的理解,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();
由于 bPtr
是 Base *
类型,如何执行多态调用 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 对象。