Buscar tipo de objeto en C++

Faiq Bilal 12 octubre 2023
  1. Encuentre el tipo de objetos de clase en C++
  2. Utilice typeid().name() para encontrar el tipo de objetos de clase en C++
  3. Utilice typeid.().name() con __cxa_demangle para encontrar el tipo de objetos de clase en C++
Buscar tipo de objeto en C++

Este artículo analiza diferentes enfoques para encontrar el tipo de objetos en C++.

Encuentre el tipo de objetos de clase en C++

Similar a cómo las variables simples tienen tipos de datos, como int, bool, etc., los objetos de clase tienen un tipo que es la clase a la que pertenecen:

#include <iostream>

using namespace std;

class Vehicles {
 public:
  string make;
  string model;
  string year;
};

int main() { Vehicles car; }

En el ejemplo anterior, el tipo de objeto coche definido en main() es la clase Vehículos, ya que coche es un objeto de Vehículos.

El ejemplo anterior fue muy simple y pudimos identificar fácilmente el tipo de objeto. Pero, en proyectos más complejos, especialmente con múltiples clases y objetos y múltiples programadores trabajando juntos, hacer un seguimiento de los tipos de objetos puede resultar muy confuso.

Para evitar este problema, podemos usar algunos métodos para determinar el tipo de un objeto, y los revisaremos con ejemplos a continuación.

Utilice typeid().name() para encontrar el tipo de objetos de clase en C++

typeid() es un método incluido en la biblioteca typeinfo. La función typeid.().name() toma una variable o un objeto de clase y devuelve el nombre de su tipo como una cadena.

El uso de la función typeid.().name() se muestra a continuación:

#include <iostream>
#include <typeinfo>

using namespace std;

class Vehicles {
 public:
  string make;
  string model;
  string year;
};

class Aircraft {
 public:
  string make;
  string model;
  string year;
};

int main() {
  int x;
  float y;
  bool b;

  Vehicles car;
  Aircraft helicopter;

  cout << "The type of the variable x "
       << " is " << typeid(x).name() << endl;
  cout << "The type of the variable y "
       << " is " << typeid(y).name() << endl;
  cout << "The type of the variable b "
       << " is " << typeid(b).name() << endl;
  cout << "The type of the object car "
       << " is " << typeid(car).name() << endl;
  cout << "The type of the object helicopter "
       << " is " << typeid(helicopter).name() << endl;
}

El fragmento de código anterior produce el siguiente resultado:

The type of the variable x  is i
The type of the variable y  is f
The type of the variable b  is b
The type of the object car  is 8Vehicles
The type of the object helicopter  is 8Aircraft

Como se vio anteriormente, la función typeid.().name() funciona tanto para variables simples como para objetos de clase definidos por el usuario. La función devuelve i, f y b para int, float y bool, respectivamente.

La función devuelve los nombres de sus respectivas clases para los objetos coche y helicóptero. Es importante tener en cuenta que los nombres de las clases de salida tienen un número 8 delante de ellos en este ejemplo debido a cómo se almacenan los nombres de clases y variables en el contexto de C++.

La función typeid.().name() depende del sistema y del compilador cuando se usa con objetivos de clase y puede agregar cualquier carácter arbitrario antes del nombre de la clase al devolverlo. En el sistema que se utiliza, el compilador agrega el número de caracteres en el nombre de la clase antes del nombre de la clase, es decir, tanto Vehículo como Aeronave tienen 8 letras en sus nombres.

Dado que typeid.().name() depende de la implementación, devuelve un nombre de clase alterado que, a su vez, se puede modificar mediante el comando c++filt o __cxa_demangle.

A pesar de que el nombre de la clase se devuelve alterado, sigue siendo legible y se puede utilizar para identificar la clase del objeto. Y dado que el tipo de retorno es una cadena, los objetos se pueden comparar fácilmente para verificar si tienen la misma clase.

Utilice typeid.().name() con __cxa_demangle para encontrar el tipo de objetos de clase en C++

Como se vio en el ejemplo anterior, usar typeid.().name() devuelve nombres de clases y tipos de variables alterados. Para obtener el resultado desmantelado, podemos usar la función __cxa_demangle de la biblioteca cxxabi.h.

La sintaxis de __cxa_demangle es la siguiente:

char *abi::__cxa_demangle(const char *mangled_name, char *output_buffer, size_t *length, int *status)

El uso de __cxa_demangle con typeid.().name() se muestra en el siguiente ejemplo:

#include <cxxabi.h>

#include <iostream>

using namespace std;

class Vehicles {
 public:
  string make;
  string model;
  string year;
};

class Aircraft {
 public:
  string make;
  string model;
  string year;
};

int main() {
  int x;
  float y;
  bool b;

  Vehicles car;
  Aircraft helicopter;

  cout << "The type of the variable x "
       << " is "
       << abi::__cxa_demangle(typeid(x).name(), nullptr, nullptr, nullptr)
       << endl;
  cout << "The type of the variable y "
       << " is "
       << abi::__cxa_demangle(typeid(y).name(), nullptr, nullptr, nullptr)
       << endl;
  cout << "The type of the variable b "
       << " is "
       << abi::__cxa_demangle(typeid(b).name(), nullptr, nullptr, nullptr)
       << endl;
  cout << "The type of the object car "
       << " is "
       << abi::__cxa_demangle(typeid(car).name(), nullptr, nullptr, nullptr)
       << endl;
  cout << "The type of the object helicopter "
       << " is "
       << abi::__cxa_demangle(typeid(helicopter).name(), nullptr, nullptr,
                              nullptr)
       << endl;
}

En el ámbito de este ejemplo, solo nos interesaba el primer argumento de la función __cxa_demangle, es decir, el nombre mutilado. El resto de los argumentos no fueron requeridos para este caso.

El código anterior produce el siguiente resultado:

The type of the variable x  is int
The type of the variable y  is float
The type of the variable b  is bool
The type of the object car  is Vehicles
The type of the object helicopter  is Aircraft

Como se ve en la salida, los nombres de variables y tipos devueltos están desmantelados y aparecen exactamente como lo hacen en el archivo de código.