2009-06-21 15 views
53

Je me demandais s'il était possible en C++ de récupérer le nom d'une classe sous forme de chaîne sans avoir à le coder en dur dans une variable ou un getter. Je suis conscient qu'aucune de ces informations n'est réellement utilisée lors de l'exécution, par conséquent, elle n'est pas disponible, mais existe-t-il des macros qui peuvent être créées pour créer cette fonctionnalité?Récupérer un nom de classe C++ par programme

Modifier: Peut être utile de noter que j'essaie actuellement de récupérer le nom d'une classe dérivée, et j'utilise Visual C++ 2008 Express Edition.

+0

étant donné que cela dépend du compilateur, avec quel compilateur travaillez-vous? –

+0

J'utilise visual C++ 2008 express, et je suppose qu'il serait utile de noter que j'essaie en fait de récupérer le nom d'une classe dérivée – Morgan

Répondre

84

Vous pouvez utiliser typeid:

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

Cependant, cela est déconseillé car le format n'est pas normalisée et peuvent différer entre les différents compilateurs (ou même des versions différentes du même compilateur).

+0

Intéressant, je ne savais pas à ce sujet. Cela semble fonctionner plutôt bien. Cela me donne un peu plus de texte que ce que je voulais dans la réponse, mais cela semble fonctionner plutôt bien. Merci! – Morgan

+0

Est-ce que ce travail d'il n'y a pas de méthodes virtuelles dans la classe? Je pense que RTTI ne fonctionne pas dans ce cas. Je suppose que tant que vous avez un destructeur virtuel, tout ira bien. – LeopardSkinPillBoxHat

+5

@LeopardSkinPillBoxHat: Oui, cela fonctionnera (voir §5.2.8/3 et 4). C'est une idée fausse commune que 'typeid' ne fonctionnera qu'avec des types polymorphes, probablement dû à la similarité avec les fonctionnalités RTTI. - En fait, l'utilisation de 'typeid' sur les types statiques n'a pas besoin et n'utilise pas de RTTI. L'opérateur est évalué au moment de la compilation et le résultat est compilé (à strictement parler, c'est un détail d'implémentation mais c'est la seule implémentation sensée). –

35

Si vous voulez juste pour vérifier si elle est certaine classe, puis

typeid(obj) == typeid(CSubClass) 

travaillerai toujours quelles que soient les mises en œuvre.

Sinon, un moyen pratique est de déclarer:

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

et mettre en œuvre par la sous-classe.

+0

Excellente solution. Facile, simple, fonctionne - sur chaque version :) –

+2

Facile, simple, compile. Mauvais, malheureusement. 'typeid()' renvoie un 'typeinfo *', un pointeur. Si deux pointeurs 'typeinfo *' sont égaux, ils font référence au même type, mais s'ils sont inégaux, ils peuvent toujours faire référence au même type. C'est pourquoi il existe une classe 'std :: type_index' avec la sémantique appropriée. 'std :: type_index (typeid (obj)) == std :: type_index (typeid (CSubClass))' sera vrai ** si et seulement si ** les deux types sont égaux. – MSalters

8

La commande typeid (obj) .name() donne toujours le type de la variable telle qu'elle a été déclarée, et non le type réel (classe) de l'objet. Si la variable obj est assignée à une instance d'une sous-classe de la classe pour laquelle obj a été déclarée comme, typeid ne le révèle pas, malheureusement.

+7

En utilisant GCC 4.7.3, en utilisant typeid (* somePtr) .name() me donne le nom des classes concrètes. – notlesh

+3

J'ai rencontré le même problème, mais le commentaire de @ stephelton m'a fait réaliser que je l'appelais sur un pointeur au lieu de l'objet ou de la référence et qu'il renvoyait le type du pointeur! Juste en ajoutant le '*' fixe tout. –

+0

Confirmant les deux commentaires ci-dessus pour VS. Après 'BaseClass * ptr = new SubClass;' je trouve 'typeid (ptr) .name()' donne 'la classe BaseClass *', et 'typeid (* ptr) .name()' donne 'class SubClass'. –

Questions connexes