static_cast, dynamic_cast, const_cast, reinterpret_cast: ¿cuándo usar cada uno?

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: ¿por qué C++ no perdona los errores de conversión de tipos?



¡Hola, amigo! Si alguna vez has escrito en C++, seguro te has encontrado con una situación en la que el compilador se queja por una discrepancia de tipos. Y entonces, probablemente, recuerdas el viejo y querido C-style cast: (int)x. ¿Funciona? Sí. ¿Es seguro? No. ¿Profesional? Aún menos.



En C++ hay cuatro operadores de conversión incorporados, y cada uno resuelve su propia tarea: static_cast, dynamic_cast, const_cast y reinterpret_cast. Usarlos correctamente significa escribir código que no solo funciona, sino que también es comprensible para otros desarrolladores. Y además, no falla en tiempo de ejecución con errores misteriosos.



En este tutorial, analizaremos cada cast con ejemplos reales, entenderemos cuándo aplicar cada uno y cuándo es mejor no hacer ninguna conversión. ¡Allá vamos!



static_cast: tu amigo confiable para conversiones comunes



static_cast es el cast más popular y seguro. Se utiliza para conversiones explícitas entre tipos relacionados: tipos numéricos, punteros hacia arriba/abajo en la jerarquía de herencia (sin verificación en tiempo de ejecución), enumeraciones a enteros y viceversa.



¿Cuándo usar static_cast?

  • Conversión de int a double (y viceversa).
  • Conversión de punteros dentro de una misma jerarquía de clases (upcast — seguro, downcast — se necesita estar seguro).
  • Conversión de void* a un tipo específico.
  • Llamada a constructores explícitos u operadores de conversión.


Ejemplo:

double pi = 3.14159;int approx = static_cast<int>(pi); // 3

class Base { public: virtual ~Base() = default; };class Derived : public Base { public: void foo() {} };

Base* b = new Derived;Derived* d = static_cast<Derived*>(b); // OK, pero sin verificaciónd->foo();delete b;


Importante: static_cast no realiza verificación de tipos en tiempo de ejecución. Si estás seguro de que el objeto es realmente de ese tipo, úsalo. Si no, mira dynamic_cast.



dynamic_cast: downcast seguro con verificación



dynamic_cast es el único cast que funciona solo con clases polimórficas (debe tener al menos una función virtual). Verifica en tiempo de ejecución si se puede convertir el puntero/referencia de forma segura. Si no, devuelve nullptr (para punteros) o lanza std::bad_cast (para referencias).



¿Cuándo usar dynamic_cast?

  • Cuando no estás seguro de que el objeto sea exactamente del tipo derivado.
  • Al trabajar con contenedores heterogéneos (por ejemplo, vector de Base*).
  • En patrones de diseño (por ejemplo, Visitor).


Ejemplo:

class Base { public: virtual ~Base() = default; };class Derived : public Base { public: void specific() {} };class Other : public Base {};

vector<Base*> objects = {new Derived, new Other, new Derived};

for (Base* obj : objects) { Derived* d = dynamic_cast<Derived*>(obj); if (d) { d->specific(); // seguro solo para Derived }}


Desventaja: dynamic_cast es más lento que static_cast porque requiere RTTI (Run-Time Type Information). No abuses de él en secciones críticas para el rendimiento.



const_cast: cuando necesitas eliminar la constante (¡pero con cuidado!)



const_cast es el único cast que puede eliminar (o agregar) cv-calificadores (const, volatile). Suena genial, pero en la práctica se usa raramente y solo en casos extremos.



¿Para qué sirve? A veces recibes una referencia constante a un objeto, pero necesitas llamar a una función antigua que no está marcada como const, aunque no modifica el objeto. O al trabajar con bibliotecas de C.



Ejemplo (correcto):

void printInt(const int* p) {    // antiguo                

Blogs

Book Recommendations