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中,我认为它肯定会生成异常(这更好)。