¿Cómo obtengo el tipo de una variable?


130

En C ++, ¿cómo se encuentra el tipo de una variable?



77
cout << typeid (variable) .name () << endl;
SRN

2
Utilice la búsqueda o google :) stackoverflow.com/questions/81870/print-variable-type-in-c Theharshest es rápido: D
Kariboo

14
@Kariboo, usé Google y me envió aquí.
Michael Warner

Esta pregunta no es muy clara, e incluso después de ver las diversas respuestas; de ninguna manera está claro que la pregunta busque la respuesta aceptada.
Antti Haapala

Respuestas:


157

Puede usar el operador typeid :

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

15
@David - Entonces isignifica entero en tu compilador. Los nombres devueltos no están especificados por el estándar.
Bo Persson

11
Cuando lo uso en el vector <int>, devuelve St6vectorIiSaIiEE. WTF?
Boyan Kushlev


55
Los nombres devueltos por typeidson muy abreviados, específicos del compilador y no están destinados al consumo humano. Puedes "demanglearlos" (¡ese es el término real!), Ya sea ​​en código con algo como gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html , con utilidades de línea de comandos como c++filt, o con cualquiera de varios demandantes en línea como demangler.com .
cincodenada

33

Para aserciones estáticas, se introdujo C ++ 11, decltypeque es bastante útil en ciertos escenarios.


12

Si tienes una variable

int k;

Puedes obtener su tipo usando

cout << typeid(k).name() << endl;

Vea el siguiente hilo en SO: Pregunta similar


9

La principal diferencia entre C ++ y Javascript es que C ++ es un lenguaje de tipo estático, mientras que JavaScript es dinámico.

En lenguajes de tipo dinámico, una variable puede contener cualquier cosa, y su tipo viene dado por el valor que posee, momento a momento. En lenguajes de tipo estático, el tipo de una variable se declara y no puede cambiar.

Puede haber despacho dinámico y composición y subtipo de objetos (herencia y funciones virtuales), así como despacho estático y supertipado (a través de la plantilla CRTP), pero en cualquier caso el compilador debe conocer el tipo de la variable.

Si está en posición de no saber qué es o podría ser, es porque diseñó algo ya que el lenguaje tiene un sistema de tipos dinámico.

Si ese es el caso, es mejor que reconsidere su diseño, ya que se dirige a una tierra que no es natural para el idioma que está utilizando (la mayoría es como ir en una autopista con una oruga o en el agua con un automóvil)


Si C ++ tiene un cambio dinámico, entonces creo que sería genial y typeof y parseInt, las funciones parseFloat también serán útiles, ¡pero no sé por qué los fabricantes de C ++ lo hacen tan difícil, por ejemplo! quien dice que es bueno escribir cout << "String"
Waqas Tahir

la determinación es la mejor !!!! #include <sstream> string str ("1912"); int strtointval; stringstream (str) >> strtointval;
Waqas Tahir

@Waqas Uh, ¿qué? Las personas que dicen que es lo mejor son las personas que definen el idioma, y ​​en mi opinión, tienen casi la última palabra en algo que ver con eso: buenas prácticas de codificación, por ejemplo. ¿Podrías reformular ese comentario para que tenga más sentido?
Financia la demanda de Mónica el

Estoy totalmente en desacuerdo. Java, C #, PHP, Perl, Python, etc. fueron diseñados en C y C ++ y no son orugas. (Cuando crea una aplicación de base de datos para abrir tablas de variables desde bases de datos 'desconocidas', necesita controlar el tipo de campo al esquema de variables y viceversa de una forma 'muy' dinámica '))
TomeeNS

@TomeeNS: No. Están escritos en C y C ++, no diseñados . Están diseñados para hacer su trabajo. Tienen un tipo dinámico incluso si C y C ++ no lo hacen. Eso no tiene nada de extraño.
Emilio Garavaglia

8

Por lo general, querer encontrar el tipo de una variable en C ++ es la pregunta incorrecta. Tiende a ser algo que llevas desde lenguajes de procedimiento como, por ejemplo, C o Pascal.

Si desea codificar diferentes comportamientos según el tipo, intente aprender, por ejemplo , sobrecarga de funciones y herencia de objetos . Esto no tendrá sentido inmediato en su primer día de C ++, pero continúe.


En realidad no, digamos que tienes una clase Object y una subclase Book. Ahora imagine que tiene una Caja que puede almacenar muchos Objetos, pero por alguna razón desea enumerar todos los Libros dentro de ella. Verificar el tipo es mucho más limpio y luego tener que agregar un método "type" a Object y luego anularlo en Book para devolver algo como "book"
Paulo Cesar

Al igual que con cualquier regla, hay excepciones (¡de ahí mi 'por lo general'!), Y los contenedores tienden a agregar complejidad a la teoría de tipos. Nunca me han gustado demasiado los contenedores de objetos polimórficos ... en la mayoría de los casos, los tipos de contenedores uniformes con plantilla son suficientes y son mucho más limpios.
Pontus Gagge

¿No usas plantillas?
Bryan Grace

6

Creo que tengo un caso de uso válido para usar typeid (), de la misma manera que es válido para usar sizeof (). Para una función de plantilla, necesito poner un caso especial en el código basado en la variable de plantilla, para ofrecer la máxima funcionalidad y flexibilidad.

Es mucho más compacto y fácil de mantener que usar polimorfismo, para crear una instancia de la función para cada tipo admitido. Incluso en ese caso, podría usar este truco para escribir el cuerpo de la función solo una vez:

Tenga en cuenta que debido a que el código usa plantillas, la siguiente declaración de cambio debería resolverse estáticamente en un solo bloque de código, optimizando todos los casos falsos, AFAIK.

Considere este ejemplo, donde podemos necesitar manejar una conversión si T es un tipo versus otro. Lo uso para la especialización de clase para acceder al hardware donde el hardware usará el tipo myClassA o myClassB. En una falta de coincidencia, necesito pasar tiempo convirtiendo los datos.

switch ((typeid(T)) {
  case typeid(myClassA):
    // handle that case
    break;
  case typeid(myClassB):
    // handle that case
    break;
  case typeid(uint32_t):
    // handle that case
    break;
  default:
    // handle that case
}

1
TypeId: no pude usar typeid () en Arduino. También typeid () es una verificación de tiempo de ejecución , no tiempo de compilación, por lo que no se puede usar para generar código optimizado.
Dan Truong

1
Sí, no, esto no hace lo que pensabas. typeidsimplemente no puede ser una comprobación estática en tiempo de compilación, por definición, por lo que esto no facilita ninguna optimización. For a template function, I need to special case the code based on the template variableBien, entonces lo que realmente quieres es un polimorfismo estático a través del lenguaje CRTP. Esto es exactamente lo que eso logra.
underscore_d

4

No estoy seguro de si mi respuesta ayudaría.

La respuesta corta es que realmente no necesitas / quieres saber el tipo de variable para usarla.

Si necesita dar un tipo a una variable estática, entonces simplemente puede usar auto.

En el caso más sofisticado donde desee usar "auto" en una clase o estructura, sugeriría usar template con decltype.

Por ejemplo, supongamos que está utilizando la biblioteca de otra persona y tiene una variable llamada "unknown_var" y desea ponerla en un vector o estructura, puede hacer esto totalmente:

template <typename T>
struct my_struct {
    int some_field;
    T my_data;
};
vector<decltype(unknown_var)> complex_vector;
vector<my_struct<decltype(unknown_var)> > simple_vector

Espero que esto ayude.

EDITAR: En buena medida, este es el caso más complejo en el que puedo pensar: tener una variable global de tipo desconocido. En este caso, necesitaría c ++ 14 y plantilla variable.

Algo como esto:

template<typename T> vector<T> global_var;

void random_func (auto unknown_var) {
    global_var<decltype(unknown_var)>.push_back(unknown_var);
}

Todavía es un poco tedioso, pero está lo más cerca posible de los idiomas sin tipo. Solo asegúrese de hacer referencia a la variable de plantilla, siempre coloque la especificación de plantilla allí.


2
#include <typeinfo>

...
string s = typeid(YourClass).name()

0

Si necesita hacer una comparación entre una clase y un tipo conocido, por ejemplo:

class Example{};
...
Example eg = Example();

Puedes usar esta línea de comparación:

bool isType = string( typeid(eg).name() ).find("Example") != string::npos;

que comprueba que el typeidnombre contiene el tipo de cadena (el nombre del tipo de letra tiene otros datos destrozados, por lo que es mejor hacer un en s1.find(s2)lugar de ==).


-2

Definitivamente puede ir a typeid(x).name()donde x es el nombre de la variable. En realidad, devuelve un puntero constante al tipo de datos. Ahora, mira el siguiente código.

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n = 36;
    char c = 'A';
    double d = 1.2;
    if(*(typeid(n).name()) == 'i'){
        cout << "I am an Integer variable" << endl;
    }
    if(*((char *) typeid(d).name()) == 'd'){
        cout << "I am a Double variable" << endl;
    }
    if(*((char *) typeid(c).name()) == 'c'){
        cout << "I am a Char variable" << endl;
    }
    return 0;
}

Observe cómo primero y segundo ambos si funciona.


Reconocer el tipo por el primer personaje es una muy mala idea.
Dmitry Kuzminov

¿Puedes ser más específico, Dmitry? No entendí tu punto aquí.
Pikachu

Esto solo se puede acortar a std::cout << "I'm a variable of type " << typeid(n).name(). (redactado nuevamente para evitar artefactos a / an, pero eso se puede solucionar con otra verificación). Incluso entonces, si realmente quieres una comparación, es mucho mejor hacerlotypeid(n) == typeid(int)
Zoe
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.