C++ 如何解决;纯虚拟方法称为;

C++ 如何解决;纯虚拟方法称为;,c++,polymorphism,derived-class,base-class,pure-virtual,C++,Polymorphism,Derived Class,Base Class,Pure Virtual,我理解为什么会发生这种情况,但我一直在努力解决它…下面是当我的程序退出时生成错误(从而导致崩溃)时我的代码所做的 调用的纯虚拟方法 SomeClass::~SomeClass() { BaseClassObject->SomePureVirtualMethod(this); } 我从未调用过newsomeclass,但我有一个QList,我将SomeClass*对象附加到它。SomeClass中此析构函数的作用是告诉DerivedClass从它的QList集合中删除SomeCla

我理解为什么会发生这种情况,但我一直在努力解决它…下面是当我的程序退出时生成错误(从而导致崩溃)时我的代码所做的

调用的纯虚拟方法

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

我从未调用过
newsomeclass
,但我有一个
QList
,我将
SomeClass*
对象附加到它。
SomeClass
中此析构函数的作用是告诉
DerivedClass
从它的
QList
集合中删除
SomeClass
的特定实例

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

BaseClass
=
Shape

DerivedClass
=
Triangle

SomeClass
=
ShapeProperties
拥有对
Shape


因此,我从未调用过
newshapeproperties
,但在
Triangle
内部有一个
QList
ShapeProperties
中的析构函数是告诉
Triangle
从它的
QList

集合中删除
ShapeProperties
的特定属性,调用析构函数时,继承类的析构函数已经被调用。在构造函数和析构函数中,可以有效地将对象的动态类型视为与静态类型相同。也就是说,当您从构造函数/析构函数中调用虚方法时,不会调用它们的重写版本


如果需要在析构函数中调用
SomePureVirtualMethod
,则必须在类的析构函数中调用它,在该类中,方法的实际定义是所需的。

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

为什么会发生这种情况?
构造函数或析构函数中的
this
的类型是调用其构造函数或析构函数的类型,因此动态分派在构造函数和析构函数中不起作用,正如您希望它在所有其他函数中起作用一样

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

C++03 10.4/6状态

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

如何避免它?
只需确保不要从构造函数或析构函数调用纯虚函数。

除非您了解所涉及的动态,否则不要调用构造函数或析构函数中的
virtual
方法。

可能发生这种情况的另一个原因是,这取决于您的编译器和系统,并且来自悬挂引用。释放内存的可能状态:

  • 内存可能被标记为已解除分配
  • 内存可能被故意扰乱
  • 内存可能会被重用
  • 这段记忆可能就这样留下了
最后一个是一个有趣的例子。物体“到底是什么样子的?” 在本例中,它是抽象基类的一个实例; 当然,这就是vtbl留下的方式。如果我们尝试 为这样的对象调用纯虚拟成员函数

“纯虚拟函数调用”


那么,如果我在派生构造函数中使用调用它,我怎么知道我指的是
this
的哪个实例呢?我可能误解了这一点,“如果
需要在析构函数中调用某个pureVirtualMethod
,那么你必须在类的析构函数中调用它,而你想要的方法的实际定义就是这个类的析构函数。”@user869525:简单地说,从析构函数调用
SomePureVirtualMethod
不会解析为最派生的重写。如果要调用最派生的重写,必须从实现此类重写的类的析构函数调用它。是的,我理解这一点,但它无法解决我的问题,因为我在
Some中类
,而不是
基类
派生类
拥有
基类
的实例,而
派生类
拥有
某类
列表
某类
中的析构函数需要从
列表
中删除
某类
的实例属于
DerivedClass
void DerivedClass::SomePureVirtualMethod(SomeClass* obj)
{
    //Do stuff to remove obj from a collection
}