2012-05-22 19 views
17

Capisco perché questo sta accadendo, ma sono bloccato cercando di risolverlo ... ecco cosa sta facendo il mio codice quando viene generato l'errore (quindi, portando ad un crash) quando il mio programma esce ...Come risolvere "metodo virtuale puro chiamato"

pure virtual method called

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

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

ho mai avere un invito new SomeClass ma ho un QList<SomeClass*> che aggiungo SomeClass* oggetti a Lo scopo di questo distruttore in SomeClass è comunicare a DerivedClass di rimuovere un'istanza specifica di SomeClass dalla sua raccolta di QList<SomeClass*>.

Così, in un esempio concreto ...

BaseClass = Shape

DerivedClass = Triangle

SomeClass = ShapeProperties che possiede un riferimento alla Shape

Quindi, non ho mai un chiama a new ShapeProperties ma ho uno QList<ShapeProperties*> all'interno di Triangle. Il distruttore in ShapeProperties deve indicare a Triangle di rimuovere una proprietà specifica di ShapeProperties dalla sua raccolta di QList<ShapeProperties*>.

risposta

28

Nel momento in cui viene chiamato il distruttore, il distruttore delle classi ereditate è già stato chiamato. All'interno di costruttori e distruttori, il tipo dinamico dell'oggetto può effettivamente essere considerato uguale al tipo statico. Cioè, quando chiamate metodi virtuali dall'interno dei vostri costruttori/distruttori non sono le versioni sovrascritte di quelli che vengono chiamati.

Se è necessario chiamare SomePureVirtualMethod al distruttore, sarà necessario chiamarlo all'interno del distruttore della classe in cui si trova la definizione effettiva del metodo desiderato.

+0

Quindi come faccio a sapere quale istanza di "questo" mi riferisco a se la chiamo con il costruttore derivato? – user869525

+0

@ user869525: Potresti provare a riformulare quello? Non ho capito ... –

+0

Probabilmente ho frainteso questo, "Se' SomePureVirtualMethod' deve essere chiamato al distruttore, allora dovrai chiamarlo all'interno del distruttore della classe dove è la definizione effettiva del metodo che desideri. " – user869525

8

quando si chiama il metodo virtual nel distruttore della classe Base SomeClass si chiama il metodo (SomePureVirtualMethod()) della classe Base SomeClass che è un metodo virtuale puro senza una definizione. E quindi l'errore.

Perché ciò accade?
Il tipo di this nel costruttore o nel distruttore è del tipo di cui è stato chiamato il costruttore o il distruttore e quindi la distribuzione dinamica non funziona nei costruttori e nei distruttori come ci si aspetterebbe che funzioni in tutte le altre funzioni.

Perché si blocca?
Perché chiamare una funzione virtuale pura dal costruttore o dal distruttore è un comportamento non definito .

C++ 03 10.4/6 stati

"Funzioni di membro può essere chiamato da un costruttore (o distruttore) di una classe astratta, l'effetto di rendere una chiamata virtuale (10.3) per una funzione virtuale pura, direttamente o indirettamente, per l'oggetto essere creato (o distrutto) da tale costruttore (o distruttore) non è definito. "

Come evitarlo?
Assicurati solo di non chiamare una funzione virtuale pura dal costruttore o dal distruttore.
Non chiamare i metodi virtual nel costruttore o nel distruttore a meno che non si comprendano le dinamiche coinvolte.