27

我理解为什么会发生这种情况,但我一直试图解决它......这是我的代码在我的程序退出时生成错误(因此导致崩溃)时所做的事情......

pure virtual method called

SomeClass::~SomeClass()
{
   BaseClassObject->SomePureVirtualMethod(this);
}

void DerivedClass::SomePureVirtualMethod(SomeClass* obj)
{
    //Do stuff to remove obj from a collection
}

我从来没有打电话,new SomeClass但我有一个QList<SomeClass*>我附加SomeClass*对象的电话。这个析构函数的目的SomeClass是告诉从它的集合中DerivedClass删除一个特定的实例。SomeClassQList<SomeClass*>

所以,在一个具体的例子中......

BaseClass=Shape

DerivedClass=Triangle

SomeClass=ShapeProperties拥有对Shape

所以,我从来没有打电话给,new ShapeProperties但我有QList<ShapeProperties*>一个Triangle. 中的析构函数ShapeProperties是告诉从它的集合中Triangle删除一个特定的属性。ShapePropertiesQList<ShapeProperties*>

4

3 回答 3

39

当你的析构函数被调用时,继承类的析构函数已经被调用了。在构造函数和析构函数中,可以有效地将对象的动态类型视为与静态类型相同。也就是说,当您从构造函数/析构函数中调用虚拟方法时,调用的不是它们的覆盖版本。

如果SomePureVirtualMethod需要在析构函数中调用,那么你必须在你想要的方法的实际定义所在的类的析构函数中调用它。

于 2012-05-22T17:51:31.180 回答
14

当你virtual在基类的析构函数中调用方法时,SomeClass它会调用基类的method( SomePureVirtualMethod()),SomeClass这是一个没有定义的纯虚方法。因此错误。

为什么会这样?
in 构造函数或析构函数的类型this是其构造函数或析构函数被调用的类型,因此动态调度在构造函数和析构函数中不起作用,因为您期望它在所有其他函数中起作用。

为什么会崩溃?
因为从构造函数或析构函数调用纯虚函数是未定义的行为

C++03 10.4/6 状态

“可以从抽象类的构造函数(或析构函数)调用成员函数;直接或间接对从此类构造函数创建(或销毁)的对象进行虚拟调用(10.3)的效​​果(或析构函数)未定义。”

如何避免?
只要确保您不从构造函数或析构函数调用纯虚函数即可。
除非您了解所涉及的动态,否则不要virtual在构造函数或析构函数中调用方法。

于 2012-05-22T17:54:09.420 回答
1

发生这种情况的另一个原因取决于您的编译器和系统,那就是来自悬空引用。Paul SR Chisholm 解释了释放内存的可能状态:

  • 内存可能被标记为已释放。
  • 内存可能被故意打乱。
  • 内存可能会被重用。
  • 记忆可能一直保持原样。

最后一个是一个有趣的案例。什么是“原样”的对象?在这种情况下,它是抽象基类的一个实例;当然,这就是 vtbl 留下的方式。如果我们尝试为这样的对象调用纯虚成员函数会发生什么?

“称为纯虚函数”。

于 2020-07-31T23:04:57.370 回答