Je comprends pourquoi cela se produit, mais je suis coincé à essayer de le résoudre ... voici ce que mon code fait lorsque l'erreur est générée (entraînant ainsi un crash) lorsque mon programme se termine ...
pure virtual method called
SomeClass::~SomeClass()
{
BaseClassObject->SomePureVirtualMethod(this);
}
void DerivedClass::SomePureVirtualMethod(SomeClass* obj)
{
//Do stuff to remove obj from a collection
}
Je n'ai jamais appelé new SomeClass
mais j'ai un QList<SomeClass*>
que j'ajoute SomeClass*
s'oppose à. Le but de ce destructeur dans SomeClass
est de dire à DerivedClass
de supprimer une instance spécifique de SomeClass
de sa collection de QList<SomeClass*>
.
Donc, dans un exemple concret ...
BaseClass
= Shape
DerivedClass
= Triangle
SomeClass
= ShapeProperties
qui possède une référence à Shape
Donc, je n'ai jamais appelé new ShapeProperties
mais j'ai un QList<ShapeProperties*>
à l'intérieur de Triangle
. Le destructeur dans ShapeProperties
doit dire à Triangle
de supprimer une propriété spécifique de ShapeProperties
de sa collection de QList<ShapeProperties*>
.
Au moment où votre destructeur est appelé, le destructeur des classes héritées a déjà été appelé. Dans les constructeurs et les destructeurs, le type dynamique de l'objet peut effectivement être considéré comme le même que le type statique. C'est-à-dire que lorsque vous appelez des méthodes virtuelles à partir de vos constructeurs/destructeurs, ce ne sont pas les versions supplantées d'entre elles qui sont appelées.
Si SomePureVirtualMethod
doit être appelé au niveau du destructeur, alors vous devrez l'appeler dans le destructeur de la classe où se trouve la définition réelle de la méthode souhaitée.
Lorsque vous appelez la méthode virtual
dans le destructeur de la classe Base SomeClass
, elle appelle la méthode (SomePureVirtualMethod()
) de la classe Base SomeClass
qui est un méthode virtuelle pure sans définition. Et d'où l'erreur.
Pourquoi cela se produit-il?
Le type de this
dans constructeur ou destructeur est du type dont le constructeur ou le destructeur est appelé et donc la répartition dynamique ne fonctionne pas dans les constructeurs et les destructeurs comme vous vous attendez à ce qu'il fonctionne dans tous autres fonctions.
Pourquoi ça plante?
Parce que l'appel d'une fonction virtuelle pure à partir d'un constructeur ou d'un destructeur est un Comportement non défini.
États C++ 03 10.4/6
"Les fonctions membres peuvent être appelées à partir d'un constructeur (ou destructeur) d'une classe abstraite; l'effet de faire un appel virtuel (10.3) à une fonction virtuelle pure directement ou indirectement pour l'objet créé (ou détruit) à partir d'un tel constructeur ( ou destructeur) n'est pas défini. "
Comment l'éviter?
Assurez-vous simplement que vous n'appelez pas une fonction virtuelle pure à partir du constructeur ou du destructeur.
N'appelez pas les méthodes virtual
dans le constructeur ou le destructeur à moins que vous ne compreniez la dynamique impliquée.