Domanda

I insegnare in una classe C ++ di programmazione e ho visto abbastanza classi di errori che ho una buona sensazione per come diagnosticare bug comune C ++. Tuttavia, c'è un tipo importante di errori per i quali la mia intuizione non è particolarmente buona:? quello programmazione errori causa chiamate a funzioni virtuali pure L'errore più comune che ho visto che causa questo sta chiamando un virtuale funzione da un costruttore della classe base o distruttore. Ce ne sono altri che dovrei essere a conoscenza di quando aiutare codice studente di debug?

È stato utile?

Soluzione

  

"L'errore più comune che ho visto che causa questo è chiamare una funzione virtuale da un costruttore della classe base o distruttore".

Quando un oggetto è costruito, il puntatore alla tabella di invio virtuale è inizialmente finalizzato alla massima superclasse, ed è aggiornato solo le classi intermedie costruzione completa. Quindi, è possibile chiamare accidentalmente l'attuazione virtuale pura fino al punto che una sottoclasse - con la sua funzione di override di implementazione - la costruzione è completa. Questo potrebbe essere il più sottoclasse di derivazione, o dovunque nel fratempo.

Può succedere se si segue un puntatore a un oggetto parzialmente costruito (per esempio in una condizione di competizione causa asincrona o filettato operazioni).

Se un compilatore ha motivo di pensare che conosce il tipo reale a cui un puntatore-a-base-class punti, si può ragionevolmente bypass l'invio virtuale. Si potrebbe confondere facendo qualcosa con un comportamento non definito come un cast cr.

Durante distruzione, la tabella di invio virtuale dovrebbe essere ripristinato come classi derivate vengono distrutti, quindi l'applicazione virtuale pura può essere nuovamente invocato.

Dopo la distruzione, ha proseguito l'utilizzo dell'oggetto tramite "penzoloni" puntatori o riferimenti possono richiamare la funzione virtuale pura, ma non c'è definito il comportamento in tali situazioni.

Altri suggerimenti

Qui ci sono alcuni casi in cui una chiamata virtuale puro può accadere.

  1. Utilizzo di un puntatore penzoloni - il puntatore non è un oggetto valido così la tabella virtuale a cui punta è solo memoria casuale che può contenere NULL
  2. Bad getto utilizzando un static_cast per il tipo sbagliato (o cast di tipo C) può anche causare l'oggetto si punta a non avere i metodi corretti nella sua tabella virtuale (in questo caso, almeno E 'davvero una tabella virtuale a differenza l'opzione precedente).
  3. DLL è stato scaricato - Se l'oggetto che si sta tenendo a è stato creato in un file oggetto condiviso (DLL, quindi, sl), che è stato scaricato di nuovo la memoria può essere azzerato ora

Questa situazione può verificarsi ad esempio quando il riferimento o puntatore ad un oggetto che punta a una posizione NULL, e si utilizza il riferimento all'oggetto o il puntatore per chiamare una funzione virtuale nella classe. Ad esempio:

std::vector <DerivedClass> objContainer;  
if (!objContainer.empty()) 
   const BaseClass& objRef = objContainer.front();  
// Do some processing using objRef and then you erase the first
// element of objContainer
objContainer.erase(objContainer.begin());   
const std::string& name = objRef.name();  
// -> (name() is a pure virtual function in base class, 
// which has been implemented in DerivedClass).

A questo punto oggetto memorizzato in objContainer [0] non esiste. Quando la tabella virtuale è indicizzata, senza locazione di memoria valida è stata trovata. Quindi, un errore di tempo di esecuzione è emesso dicendo "funzione virtuale pura chiamata".

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top