这不是关于“何时创建 VTABLE?” . 相反,什么时候应该初始化 VPTR?它是在构造函数的开头/结尾还是构造函数之前/之后?
A::A () : i(0), j(0) -->> here ?
{
-->> here ?
//...
-->> here ?
}
这不是关于“何时创建 VTABLE?” . 相反,什么时候应该初始化 VPTR?它是在构造函数的开头/结尾还是构造函数之前/之后?
A::A () : i(0), j(0) -->> here ?
{
-->> here ?
//...
-->> here ?
}
虚拟调用的机制(通常是一个 v-table,但不是必须的)是在ctor-initializer期间、基础子对象构建之后和成员构建之前设置的。部分[class.base.init]
法令:
可以为正在构建的对象调用成员函数(包括虚拟成员函数,10.3)。类似地,正在构造的对象可以是运算
typeid
符 (5.2.8) 或dynamic_cast
(5.2.7) 的操作数。但是,如果这些操作在基类的所有mem-initializer完成之前在ctor-initializer(或直接或间接从ctor-initializer调用的函数中)执行,则操作的结果是未定义的。
实际上,在基类子对象的构建过程中,虚函数机制是存在的,但它是为基类设置的。[ 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 对象转换为 Derived 对象时会发生这种情况。破坏物体时同样明显地发生相反的情况。即每次类型改变时,vtable 指针都会改变。(我确定有人评论说 vtables 不需要根据标准存在。)
那里说:
“最终的答案是……正如你所料。它发生在构造函数中。”
所以..
A::A () : i(0), j(0)
{
-->> 这里!
//...
//
}
但要小心,假设你有一个类 A,以及一个从 A 派生的类 A1。
“当你构造一个 A1 类的实例时,这是整个事件序列:
- A1::A1 调用 A::A
- A::A 将 vtable 设置为 A 的 vtable
- A::A 执行并返回
- A1::A1 将 vtable 设置为 A1 的 vtable
- A1::A1 执行并返回 "