Disponible la nueva versión "donationware" 7.3 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


4.9.14a   La clase type_info

§1  Sinopsis

Aunque debería ser incluida en la sección correspondiente a la Librería Estándar, incluimos aquí una descripción de la clase type_info, dado que está indisolublemente unida al operador typeid. Entrambos permiten conocer el tipo y nombre de un objeto en tiempo de ejecución ( 4.9.14).

La definición de esta clase está incluida en la cabecera estándar <typeinfo>, y tiene un único constructor por defecto que excepcionalmente es privado (lo normal es que sean públicos), por lo que el usuario no puede instanciar directamente objetos de la clase; en cambio, el operador typeid sí puede generar estos objetos; precisamente devuelve una referencia a ellos.

  Para poder utilizar la clase type_info es necesario incluir en el programa la el fichero de cabecera <typeinfo>.

§2  Uso

La forma de obtener una referencia a la instancia de type_info generada por typeid es como sigue:

int* ptr;
const type_info & ref1 = typeid(float);
const type_info & ref2 = typeid(ptr);

En este caso, ref1 y ref2 representan referencias a dos instancias de la clase type_info que describen los tipos de un float y de la variable ptr (que sabemos por la primera línea es un puntero-a-int).

§3  Interfaz

En lo que respecta al interfaz, esta clase solo tiene dos métodos públicos, type_info::name y type_info::before, así como dos operadores: de igualdad ( == ) y de desigualdad ( != ).

Por ejemplo, siguiendo con el código anterior, podríamos añadir:

const char* ptr = ref1.name();
if ( ref1.before(ref2) ) { cout << "Float anterior que puntero-a-int" << endl; }
if ( ref1 == ref2 ) { cout << "Inexplicablemente son iguales!! << endl; }


En ocasiones la referencia devuelta por typeid es utilzada implícitamente. Por ejemplo:

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

§3.1  Método type_info::name

El método name() tiene la definición: const char* name() const,  lo que significa que no acepta argumentos y devuelve un puntero constante a constante carácter; concretamente a una cadena que identifica el nombre del tipo del operando utilizado con typeid. El espacio ocupado por esta cadena de caracteres es machacado con cada nueva invocación al operador.

Ejemplo:

float X;
float* fptr;
cout << typeid(X).name();
cout << typeid(fptr).name();

Salida:

float
float*

§3.2  Método  type_info::before

La definición del método before() es:  int before(const type_info&). En otras palabras: esta función devuelve un entero y acepta como argumento la referencia a un objeto constante de la clase type_info, es decir, puede pasarse como argumento el resultado del operador typeid.

El entero devuelto es 0 o 1, según que el orden léxico de la expresión pasada como argumento sea o no anterior al operando utilizado en typeid, lo que permite comparar el orden léxico ( ) de dos tipos.

Ejmplo: sean los tipos T1 y T2; para comparar su orden debe utilizarse la expresión typeid(T1).before( typeid(T2) ). El valor x devuelto será 0 o 1 según que el orden léxico del tipo T1 sea o no anterior a T2. Veámoslo en un ejemplo compilable:

#include <iostream>
#include <typeinfo>
using namespace std;
 
void main() {       // =============
   cout << "int antes que double: " <<
       typeid(int).before(typeid(double)) << endl;
   cout << "double antes que int: " <<
       typeid(double).before(typeid(int)) << endl;

   char C;
   float F;
   int T = typeid(C).before(typeid(F));

   cout << "char antes que float: " << T << endl;
   T = typeid(F).before(typeid(C));
   cout << "float antes que char: " << T << endl;
}

Salida:

int antes que double: 0
double antes que int: 1
char antes que float: 1
float antes que char: 0

Nota: el orden léxico aludido es un orden que establece el compilador para los diversos tipos. Este orden no está definido (por el Estándar), es decir, depende de la implementación. Simplemente sirve para poder establecer un cierto orden entre los tipos, lo que puede ser de utilidad en determinadas circunstancias, y no tiene ninguna relación con posibles relaciones de jerarquía de clases.

§3.3  Operadores de comparación

Hemos indicado que los operadores == y != de la clase permiten comparaciones entre objetos type_info. Naturalmente, corresponden a los métodos type_info::operator==() y type_info::operator!=().

A continuación se muestra un ejemplo de su uso:

#include <iostream>
#include <typeinfo>
using namespace std;

void main() {       // ==========
  float F = 3.14;
  double D = 3.14;

  cout << "Son iguales los tipos F y D? " <<
     ( typeid(F) == typeid(D) ? "Cierto" : "Falso" ) << endl;

  cout << "Son desiguales los tipos F y D? " <<
     ( typeid(F) != typeid(D) ? "Cierto" : "Falso" ) << endl;
}

Salida:

Son iguales los tipos F y D? Falso
Son desiguales los tipos F y D? Cierto


§3.4
  A título de ejemplo, se incluye la definición de la clase type_info del compilador C++Builder, tal como aparece en la cabecera <typeinfo.h>

class _TIDIST __rtti type_info {

public: tpid * tpp;

private:
  __cdecl type_info(const type_info &);
  type_info & __cdecl operator=(const type_info &);

public:
  virtual __cdecl ~type_info();
  bool __cdecl operator==(const type_info &) const;
  bool __cdecl operator!=(const type_info &) const;
  bool __cdecl before(const type_info &) const;
  const char *__cdecl name() const;

/* funciones miembro y tipos extra específicos de Borland. Sirven para traslación GUID dinámica y modelado. */
  void * __cdecl _internal_rtti_cast(void *srcObj, const type_info
  *srcType) const;

  template <class _SrcType>
  void * __cdecl _rtti_cast(_SrcType *_src) const {
    // do the typeid() inline so the compiler will flag an error
    // if the _SrcType doesn't support rtti.
    return _internal_rtti_cast(_src, (const type_info*)&
           typeid(_SrcType));
  }
  const _BORGUID *__cdecl _guid() const;

  struct _base_info {
    type_info *_type;
    void *_cookie;
  };

  struct _vbase_info : public _base_info {
    bool _indirect();
  };

  type_info const *_first_base(_base_info &) const;
  type_info const *_next_base(_base_info &) const;
  type_info const *_first_vbase(_vbase_info &) const;
  type_info const *_next_vbase(_vbase_info &_vb) const {
    return _next_base(_vb);
  }

protected:  __cdecl type_info(tpid *_tpp) { tpp = _tpp; }
};