2009-06-21 5 views
53

Mi chiedevo se è possibile in C++ recuperare il nome di una classe in forma stringa senza doverlo codificare in una variabile o in un getter. Sono consapevole che nessuna di queste informazioni è effettivamente utilizzata in fase di runtime, quindi non è disponibile, ma ci sono macro che possono essere create per creare questa funzionalità?Recupero di un nome di classe C++ a livello di codice

Modifica: potrebbe essere utile notare che sto effettivamente cercando di recuperare il nome di una classe derivata e sto utilizzando Visual C++ 2008 Express Edition.

+0

poiché questo dipende dal compilatore, con che compilatore si lavora? –

+0

Sto usando Visual C++ 2008 Express, e credo che sarebbe utile notare che sto effettivamente cercando di recuperare il nome di una classe derivata – Morgan

risposta

84

È possibile utilizzare typeid:

#include <typeinfo> 
cout << typeid(obj).name() << endl; 

Tuttavia, questo è sconsigliato in quanto il formato non è standardizzata e può differire tra i diversi compilatori (o anche diverse versioni dello stesso compilatore).

+0

Interessante, non sapevo di questo. Sembra funzionare abbastanza bene. Mi dà un po 'più di testo di quello che volevo nella risposta, ma sembra funzionare piuttosto bene. Grazie! – Morgan

+0

Questo lavoro non prevede metodi virtuali nella classe? Anche se RTTI non funziona in questo caso. Immagino che finché avrai un distruttore virtuale starai bene. – LeopardSkinPillBoxHat

+5

@LeopardSkinPillBoxHat: Sì, funzionerà (consultare §5.2.8/3 e 4). È un'idea sbagliata comune che 'typeid' funzionerà solo con tipi polimorfici, probabilmente derivanti dalla somiglianza con le funzionalità RTTI. - In effetti, l'uso di 'typeid' su tipi statici non ha bisogno e RTTI non lo usa. L'operatore viene valutato in fase di compilazione e il risultato viene compilato (in senso stretto, si tratta di un dettaglio di implementazione ma è l'unica sana implementazione). –

35

Se si desidera solo per verificare se è certa classe, quindi

typeid(obj) == typeid(CSubClass) 

sarà sempre lavorare indipendentemente dalle implementazioni.

Altrimenti, un modo conveniente è dichiarare:

virtual const char* classname() { return "CMyClass";} 

e implementare per sottoclasse.

+0

Ottima soluzione. Facile, semplice, funziona - su ogni versione :) –

+2

Facile, semplice, compila. Sbagliato, sfortunatamente. 'typeid()' restituisce un 'typeinfo *', un puntatore. Se due puntatori 'typeinfo *' sono uguali, si riferiscono allo stesso tipo, ma se non sono uguali possono ancora riferirsi allo stesso tipo. Ecco perché esiste una classe 'std :: type_index' con una semantica corretta. 'std :: type_index (typeid (obj)) == std :: type_index (typeid (CSubClass))' sarà vero ** se e solo se ** i due tipi sono uguali. – MSalters

8

La cosa typeid (obj) .name() fornisce sempre il tipo della variabile come è stata dichiarata, non il tipo effettivo (classe) dell'oggetto. Se la variabile obj è assegnata a un'istanza di una sottoclasse della classe che obj è stata dichiarata come, typeid non lo rivela, sfortunatamente.

+7

Utilizzando GCC 4.7.3, l'uso di typeid (* somePtr) .name() mi dà il nome delle classi concrete. – notlesh

+3

Mi sono imbattuto nello stesso problema, ma il commento di @ stephelton mi ha fatto capire che lo stavo chiamando su un puntatore anziché sull'oggetto o sul riferimento effettivo e restituiva il tipo di puntatore! Aggiungendo semplicemente "*" è stato corretto tutto. –

+0

Conferma di entrambi i commenti sopra per VS. Dopo 'BaseClass * ptr = new SubClass;' Find' typeid (ptr) .name() 'produce' class BaseClass * ', e' typeid (* ptr) .name() 'fornisce' classClass SubClass'. –