2013-04-09 9 views
14

Diciamo che abbiamo una gerarchia di classi. In fondo abbiamo Base e nella parte superiore Derivato. Come determinare la classe dell'oggetto anche se è convertita nel puntatore della classe base.Come determinare il tipo di oggetto effettivo in fase di runtime in C++;

Base* b = new Derived(): 

typeid(b).name(); // i want this to tell me that this is actually derived not base object 

c'è un modo diverso dall'implementazione manuale del campo di stringa o di tale funzione di ottenimento virtuale?

PS: si parla di compilatore indipendente soluzione

+3

Questo è possibile come spiegato nella risposta, ma questa è quasi sempre una cosa sbagliata da fare. Cosa stai cercando di ottenere qui? –

+0

Niente esattamente è solo per lo scopo di argomentare :) – user1079475

+1

Più versione orientata all'applicazione: http://stackoverflow.com/questions/351845/finding-the-type-of-an-object-in-c || Versione più generica che non menziona l'ereditarietà: http://stackoverflow.com/questions/11310898/how-do-i-get-the-type-of-a-variable –

risposta

26

assicurarsi che la classe di base ha almeno un metodo virtuale, includono <typeinfo> e utilizzare il codice corrente solo con una ulteriore dereferenziazione, typeid(*b).name().


di passaggio, si noti che una chiamata typeid è l'unico posto in C++ dove si può dereference un nullpointer con un comportamento ben definito, il che implica che essa può generare un'eccezione:

C++ 11 § 5.2.8/2:
“ Se l'espressione glvalue si ottiene applicando la * operatore unario a un puntatore e il puntatore è un valore puntatore nullo (4.10), l'espressione typeid genera l'eccezione std::bad_typeid (18.7.3) . ”

+4

È una buona idea avere un distruttore come "at almeno un metodo virtuale " –

8

Se tutto quello che vogliamo fare è trovare se b in realtà punta a Derived, basta usare dynamic_cast():

if (dynamic_cast<Derived*>(b)) { ... } 

dynamic_cast restituisce un puntatore nullo se il tipo di esecuzione effettivo dell'oggetto puntato da b non è Derived (o una classe derivata da Derived). A differenza del membro name() di std::type_info, questo è il compilatore-invariante.

Si noti che questo funziona solo se Base ha almeno un membro virtuale funzioni. Quale dovrebbe comunque, dal momento che stai manipolando i tipi derivati ​​da esso tramite un puntatore di base, quindi dovrebbe avere un distruttore virtuale.

+0

Ma il caso è che non voglio modificare il codice ogni volta che aggiungo nuova classe. – user1079475