Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当析构函数调用抽象函数时会发生什么_C++_Constructor_Crash_Virtual_Abstract - Fatal编程技术网

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

C++ 当析构函数调用抽象函数时会发生什么,c++,constructor,crash,virtual,abstract,C++,Constructor,Crash,Virtual,Abstract,我无法理解以下代码中崩溃的原因: 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(); } A

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

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();
}
A类{
公众:
虚拟~A(){goo();}
void goo(){absFoo();}
虚空absFoo()=0;
};
B类:公共A{
公众:

void absFoo(){cout当对象解构时,vtable将更新以匹配对象的新状态

由于您已经删除了最后一个函数,编译器将执行它认为合适的任何操作;在VisualStudio中进行调试编译时,这将返回到中止报告,报告调用了纯虚拟函数

然而,vtable不是标准的一部分,它是一个实现细节,您的程序不需要崩溃;它只是调用纯虚拟函数时被认为是最好的方法

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

首先,让我们考虑析构函数调用任何虚函数(同样适用于构造函数的方法):当虚函数<代码> FoO 被调用在<代码> t>代码>的析构函数中时,调用将不会动态地发送到派生类型的实现中。(任何派生对象的生存期都已经结束),但是静态地执行

T::foo


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

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

当一个虚函数直接或间接地从 构造函数或析构函数(包括在构造或 销毁类的非静态数据成员,例如在成员中 初始值设定项列表),调用应用的对象是 对象,调用的函数是 构造函数或析构函数类中的最终重写器,而不是 在更派生的类中重写它

换句话说,在构造或销毁期间,不存在更多派生类。


旁白:main必须返回int,而不是void。实际上,您不能直接从
A
的析构函数调用
absFoo
。在这种情况下,程序不会编译,句号。原因是它是非法的。语言规范也不会保护您不违反此规则。这与另一个问题类似@Martin-您已经有了e问题的答案::-)在一个单独的函数中隐藏
absFoo
调用没有任何区别-当您输入a时,a的析构函数B已经消失,而
的动态类型是
a*
。现在我明白了,我的错误是认为在另一个函数中“隐藏”纯虚拟函数会有任何区别,但这并没有改变重要的是,它是在这个阶段静态实现的(销毁)。谢谢!注意:虽然理论上调用纯虚拟函数是UB,但实际上在安腾ABI中,我认为它肯定会生成异常(这更好)。