2009-06-21 13 views
53

Me preguntaba si es posible en C++ recuperar el nombre de una clase en forma de cadena sin tener que codificarlo en una variable o un getter. Soy consciente de que ninguna de esa información se usa realmente en tiempo de ejecución, por lo tanto no está disponible, pero ¿hay alguna macro que se pueda crear para crear esta funcionalidad?Recuperando un nombre de clase de C++ programáticamente

Editar: Puede ser útil tener en cuenta que en realidad estoy tratando de recuperar el nombre de una clase derivada, y estoy usando Visual C++ 2008 Express Edition.

+0

ya que esto depende del compilador, ¿con qué compilador trabajas? –

+0

Estoy usando visual C++ 2008 express, y supongo que sería útil tener en cuenta que estoy tratando de recuperar el nombre de una clase derivada – Morgan

Respuesta

84

Puede utilizar typeid:

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

Sin embargo, esto no se recomienda ya que el formato no está estandarizada y puede diferir entre los diferentes compiladores (o incluso diferentes versiones del mismo compilador).

+0

Interesante, no sabía sobre esto. Parece que funciona bastante bien. Me da un poco más de texto de lo que quería en la respuesta, pero parece funcionar bastante bien. ¡Gracias! – Morgan

+0

¿Este trabajo de no hay métodos virtuales en la clase? Creo que RTTI no funciona en este caso. Supongo que mientras tengas un destructor virtual estarás bien. – LeopardSkinPillBoxHat

+5

@LeopardSkinPillBoxHat: Sí, funcionará (ver §5.2.8/3 y 4). Es un concepto erróneo común que 'typeid' solo funcionará con tipos polimórficos, probablemente debido a la similitud con las características de RTTI. - De hecho, usar 'typeid' en tipos estáticos no necesita, y no usa, RTTI. El operador se evalúa en tiempo de compilación y el resultado se compila (estrictamente hablando, eso es un detalle de implementación, pero es la única implementación sensata). –

35

Si lo que desea es comprobar si es cierta clase, entonces

typeid(obj) == typeid(CSubClass) 

siempre funcionará independientemente de las implementaciones.

De lo contrario, una manera conveniente es declarar:

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

e implementar por subclase.

+0

Gran solución. Fácil, simple, funciona - en cada versión :) –

+2

Fácil, simple, compila. Incorrecta, desafortunadamente. 'typeid()' devuelve un 'typeinfo *', un puntero. Si dos punteros 'typeinfo *' son iguales, se refieren al mismo tipo, pero si son desiguales todavía pueden referirse al mismo tipo. Es por eso que hay una clase 'std :: type_index' con una semántica adecuada. 'std :: type_index (typeid (obj)) == std :: type_index (typeid (CSubClass))' será verdadero ** si y solo si ** los dos tipos son iguales. – MSalters

8

La cosa typeid (obj) .name() siempre da el tipo de la variable tal como fue declarada, no el tipo (clase) real del objeto. Si la variable obj se asigna a una instancia de una subclase de la clase que obj se declaró como, typeid no lo revela, desafortunadamente.

+7

Utilizando GCC 4.7.3, el uso de typeid (* somePtr) .name() me da el nombre concreto de las clases. – notlesh

+3

Me encontré con el mismo problema, pero el comentario de @ stephelton me hizo darme cuenta de que estaba llamando a un puntero en lugar de al objeto o referencia real y me devolvía el tipo del puntero. Simplemente agregando el '*' arreglado todo. –

+0

Confirmando los dos comentarios anteriores para VS. Después de 'BaseClass * ptr = new SubClass;' Encuentro 'typeid (ptr) .name()' produce 'class BaseClass *', y 'typeid (* ptr) .name()' da 'clase SubClass'. –

Cuestiones relacionadas