web-dev-qa-db-fra.com

Comment résoudre la «méthode virtuelle pure appelée»

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*>.

19
user869525

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.

30
K-ballo

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.

10
Alok Save