» » Curso De C++ - Capitulo 42

Curso De C++ - Capitulo 42

Operador dynamic_cast<>

La sintaxis de este operador es:
dynamic_cast<tipo> (<objeto>);
Se usa para hacer cambios de tipo durante la ejecución. Y se usa la base de datos formada por las estructuras type_info que vimos antes.

Este operador sólo puede usarse con objetos polimórficos, cualquier intento de aplicarlo a objetos de tipos fundamentales o agregados o de clases no polimórficas dará como resultado un error.
Hay dos modalidades de dynamic_cast, una usa punteros y la otra referencias:
class Base { // Clase base virtual
...
};
 
class Derivada : public Base { // Clase derivada
...
};

// Modalidad de puntero:
Derivada *p = dynamic_cast<Derivada *> (&Base);
// Modalidad de referencia:

Derivada &refd = dynamic_cast<Derivada &> (Base); 
Lo que el programa intentará hacer, durante la ejecución, es obtener bien un puntero o bien una referencia a un objeto de cierta clase base en forma de clase derivada, pero puede que se consiga, o puede que no.

Esto es, en cierto modo, lo contrario a lo que hacíamos al usar polimorfismo. En lugar de obtener un puntero o referencia a la clase base a partir de la derivada, haremos lo contrario: intentar obtener un puntero o referencia a la clase derivada a partir de la clase base.

Volvamos a nuestro ejemplo de Personas.

Vamos a añadir un miembro "sueldo" a la clase "Empleado", y la modificaremos para poder inicializar y leer ese dato.

También crearemos una función "LeerSueldo" que aceptará como parámetro un puntero a un objeto de la clase "Persona":
#include <iostream>
#include <cstring>
using namespace std;
 
class Persona { // Virtual
  public:
   Persona(char *n) { strcpy(nombre, n); }
   virtual void VerNombre() = 0; // Virtual pura
  protected:
   char nombre[30];
};

class Empleado : public Persona {
  public:
   Empleado(char *n, float s) : Persona(n), sueldo(s) {}
   void VerNombre() { 
      cout << "Emp: " << nombre << endl; 
   }
   void VerSueldo() {
      cout << "Salario: " << sueldo << endl; 
   }   
  private:
   float sueldo;
};

class Estudiante : public Persona {
  public:
   Estudiante(char *n) : Persona(n) {}
   void VerNombre() { 
      cout << "Est: " << nombre << endl;
   }
};

void VerSueldo(Persona *p) {
   if(Empleado *pEmp = dynamic_cast<Empleado *> (p))
      pEmp->VerSueldo();
   else
      cout << "No tiene salario." << endl;
}

int main() {
   Persona *Pepito = new Estudiante("Jose");
   Persona *Carlos = new Empleado("Carlos", 1000.0);

   Carlos->VerNombre();
   VerSueldo(Carlos);

   Pepito->VerNombre();
   VerSueldo(Pepito);

   delete Pepito;
   delete Carlos;
   
   return 0;
} 
La función "VerSueldo" recibe un puntero a un objeto de la clase base virtual "Persona". Pero a priori no sabemos si el objeto original era un empleado o un estudiante, de modo que no podemos prever si tendrá o no sueldo. Para averiguarlo hacemos un casting dinámico a la clase derivada "Empleado", y si tenemos éxito es que se trata efectivamente de un empleado y mostramos el salario. Si fracasamos, mostramos un mensaje de error.

Pero esto es válido sólo con punteros, si intentamos hacerlo con referencias tendremos un serio problema, ya que no es posible declarar referencias indefinidas. Esto quiere decir que, por una parte, no podemos usar la expresión del casting como una condición en una sentencia if. Por otra parte, si el casting fracasa, se producirá una excepción, ya que se asignará un valor nulo a una referencia durante la ejecución:
void VerSueldo(Persona &p) {
   Empleado rEmp = dynamic_cast<Empleado &> p;
... 
Por lo tanto tendremos que usar manejo de excepciones (que es el tema del siguiente capítulo), para usar referencias con el casting dinámico:
void VerSueldo(Persona &p) {
   try {
      Empleado rEmp = dynamic_cast<Empleado &> p;
      rEmp.VerSueldo();
   }
   catch (std::bad_cast) {
      cout << "No tiene salario." << endl;
   }
} 

Castings cruzados

Cuando tenemos una clase producto de una derivación múltiple, es posible obtener punteros o referencias a una clase base a partir de objetos o punteros a objetos de otra clase base, eso sí, es necesario usar polimorfismo, no podemos usar un objeto de una clase base para obtener otra. Por ejemplo:
#include <iostream>
using namespace std;

class ClaseA {
  public:
   ClaseA(int x) : valorA(x) {}
   void Mostrar() {
      cout << valorA << endl;
   }
   virtual void nada() {} // Forzar polimorfismo
  private:
   int valorA;
};

class ClaseB {
  public:
   ClaseB(float x) : valorB(x) {}
 
Capitulo 43  | Ir al Principio

Deja un comentario

Información
Atención! Usuarios que están en este grupo no pueden dejar comentarios en la página...Primero debes Registrarse!

Redes Sociales

Cómo publicar videos más largos en tus historias de Instagram

Cómo publicar videos más largos en tus historias de Instagram

Si a veces subes videos a tus historias de Instagram , probablemente te has topado con el límite de 15 segundos. Eso significa que no importa la duración del video que publiques en tu historia, Instagram lo recortará automáticamente a una duración máxima de 15 segundos. Esto es ideal para videos...
Recupera Tus Mensajes O Chats De WhatsApp Borrados

Recupera Tus Mensajes O Chats De WhatsApp Borrados

  Recuperar mensajes y chats borrados de tu aplicación WhatsApp para Android es una tarea que puede resultar  necesaria alguna vez. A menudo, estamos tratando de liberar espacio físico de nuestro dispositivo Android y llegamos incluso a borrar...
Integrar El Boton de Whatsapp En Tu Web

Integrar El Boton de Whatsapp En Tu Web

  De todos es conocido que WhatsApp se ha convertido en una herramienta para compartir fotos y vídeos con tus amigos, familiares y compañeros de trabajo. También cada vez más usado, para compartir enlaces de contenidos de la web y otras aplicaciones móviles. Para ayudar a compartir los contenidos...
Crees que las redes sociales te están haciendo bien o mal

Crees que las redes sociales te están haciendo bien o mal

Las redes sociales te ofrecen una forma única de observar a la gente. Por ejemplo, el lenguaje utilizado en Twitter puede usarse para predecir si alguien está en riesgo de morir de una enfermedad cardíaca. El análisis de las actualizaciones de Facebook muestra que las mujeres son generalmente más...
Crea una imagen para las redes sociales

Crea una imagen para las redes sociales

Aprenda a combinar una foto, texto y material gráfico en Photoshop para su Facebook, Twitter y otras publicaciones en redes sociales. Utilice estas habilidades para crear sus propias imágenes de redes sociales o cualquier diseño que cree en Photoshop. Adobe Photoshop es un editor de gráficos...
Comparte instantáneamente tus fotos y diseños

Comparte instantáneamente tus fotos y diseños

Muestre rápidamente su trabajo a clientes y compañeros de trabajo, o comparta una idea al instante por correo electrónico, texto, redes sociales y más, todo dentro de Adobe Photoshop CC. Nota: Necesitará la última versión de Photoshop CC para usar esta función. Comparte tu trabajo ahoraHaz clic en...