我遇到这种情况:
#include <iostream>
struct B { virtual void f() { std::cout << "base"; } };
struct A {
~A() {
b->f();
}
B *b;
};
struct Bd : B {
Bd():a{this}{ }
~Bd() { }
virtual void f() { std::cout << "derived"; }
A a;
};
int main() {
Bd d;
}
是否保证打印&#34;派生&#34;?
答案 0 :(得分:2)
成员函数,包括虚函数([class.virtual]),可以 在施工或毁坏期间被召唤([class.base.init])。什么时候 虚函数直接或间接从构造函数调用 或者来自破坏者,包括在施工或破坏期间 类的非静态数据成员以及该对象的对象 call apply是正在构建的对象(称为
x
)或 破坏,所谓的函数是最终的覆盖者 构造函数或析构函数的类,而不是一个覆盖它的类 更多派生的类。
&#34;班级&#34;这里的问题是Bd
,因此它应该在f()
中调用Bd
的最终覆盖者,然后打印derived
。
答案 1 :(得分:0)
我现在没有时间查找它,但规则是对析构函数正在运行的对象的虚拟调用将转到析构函数当前正在运行的类。因此,在Bd
的析构函数中,a
的析构函数运行,调用b->f()
调用Bd::f
。
如果a
成为B
而非Bd
的成员,则调用将转到B::f
,因为a
的析构函数将从B
的析构函数。
如果您更愿意考虑机制(我通常不会这样做),请考虑vtable;在进入析构函数时,代码将vtable指针设置为指向属于正在运行的析构函数的vtable。