vptr(指向 vtable)何时初始化为多态类

When does the vptr (pointing to vtable) get initialized for a polymorphic class?

本文关键字:初始化 多态 何时 指向 vtable vptr      更新时间:2023-10-16
这与

"何时创建VTABLE?"无关。相反,何时应初始化 VPTR?是在构造函数的开头/结尾还是在构造函数之前/之后?

A::A () : i(0), j(0)  -->> here ?
{
  -->> here ?
  //...
  -->> here ?
}

虚拟调用的机制(通常是 v-table,但不需要(是在 ctor 初始值设定项期间、构造基本子对象之后和构造成员之前设置的。 第[class.base.init]条法令:

可以为正在构造的对象调用成员函数(包括虚拟成员函数 10.3(。同样,正在构造的对象可以是typeid运算符 (5.2.8( 或dynamic_cast (5.2.7( 的操作数。但是,如果在基类的所有 mem 初始值设定项完成之前在 ctor-初始值设定项(或在从 ctor-初始值设定项直接或间接调用的函数(中执行这些操作,则操作的结果是未定义的。

实际上,在构造基子对象期间,虚函数机制是存在的,但它是为基类设置的。 第 [ class.cdtor 节 ] 说:

成员函数,包括虚函数 (10.3(,可以在构造或销毁 (12.6.2( 期间调用。当从构造函数或析构函数直接或间接调用虚函数时,包括在构造或销毁类的非静态数据成员期间,并且调用适用的对象是正在构造或销毁的对象(调用它x(,则调用的函数是最终重写器 在构造函数或析构函数的类中,而不是在派生更多的类中重写它。 如果虚拟函数调用使用显式类成员访问 (5.2.5(,并且对象表达式引用x的完整对象或该对象的基类子对象之一,但不是x或其基类子对象之一,则行为是未定义的。

它在基类和派生类的构造函数之间初始化:

class Base { Base() { } virtual void f(); };
class Derived { Derived(); virtual void f(); };

当原始内存转换为 Base 对象时,就会发生这种情况。当 Base 对象在对象构造期间转换为派生对象时,就会发生这种情况。在销毁物体时,显然也会反过来发生同样的情况。即每次类型更改时,vtable指针已更改。(我敢肯定有人评论说,根据标准,vtables 不需要存在。

这篇

msdn 文章用大 detali 解释了它

那里说:

"最后的答案是...如您所料。它发生在构造函数中。

所以。。
A::A (( : i(0(, j(0(

{ -->>在这里!
//...

}

但要小心,假设你有 A 类,以及从 A 派生的 A1 类。

  • 如果创建新的 A 对象,vptr 将设置在 A 类构造函数的开头
  • 但是,如果要创建新对象 A1:

"这是构造类 A1 实例时的整个事件序列:

    A1::
  1. A1 呼叫 A::A
  2. A::A 将 vtable
  3. 设置为 A 的 vtable
  4. A::A 执行并返回
  5. A1:
  6. :A1 将 vtable 设置为 A1 的 vtable
  7. A1::A1 执行并返回">