当析构函数调用抽象函数时会发生什么

What happens when a destructor calls an abstract function

我无法理解以下代码崩溃的原因:

class A {
public:
    virtual ~A() { goo(); }
    void goo() { absFoo(); }
    virtual void absFoo() = 0;

};

class B : public A {
public:
    void absFoo() { cout << "In B \n"; }
};

int main() 
{
    B b1;
    b1.goo();
}

main按预期打印了"In B",但是最后崩溃了,我也无法调试,编译器弹出一个奇怪的消息。

所以我的问题是,当 A 的析构函数调用 "goo()" 时,"absFoo()" 会崩溃吗 因为我们指的是抽象函数?

或者编译器真的在派生的类中寻找定义吗?(并且它不再存在因为它被预先破坏所以它崩溃了)

我知道如果我们直接从析构函数中调用 "absFoo()",原因应该是抽象函数。但是因为这是一个外部函数调用 "absFoo()" 我很难理解真正的原因。

随着对象被解构,vtable 被更新以匹配对象的新状态。

由于您删除了最后一个函数,编译器将执行它认为合适的任何操作;在 visual studio 中的调试编译的情况下,将回退到中止报告调用了纯虚函数。

然而,vtable 不是标准的一部分,它是一个实现细节,并且不需要您的程序崩溃;当您调用纯虚函数时,这就是被认为是最好的事情。

What happens when a destructor calls an abstract function

首先,让我们考虑当析构函数调用任何虚函数时会发生什么(顺便说一句,这同样适用于构造函数):当在[=11=的析构函数中调用虚函数foo时],调用将不会动态分派到派生类型中的实现(任何派生对象的生命周期已经结束),而是静态地分派到实现 T::foo.

如果 T::foo 是纯虚拟的,那么在没有动态调度的情况下调用它将会有未定义的行为。这就是在析构函数(或构造函数)中(间接)调用纯虚函数时发生的情况。

为了补充已经接受的答案,这是来自 cppreference 的文档。

When a virtual function is called directly or indirectly from a constructor or from a destructor (including during the construction or destruction of the class’s non-static data members, e.g. in a member initializer list), and the object to which the call applies is the object under construction or destruction, the function called is the final overrider in the constructor’s or destructor’s class and not one overriding it in a more-derived class.

In other words, during construction or destruction, the more-derived classes do not exist.