Inicia sesión


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

Te sugiero seguir leyendo...

  • Autor:
  • Editor: Tutoriales En Linea
  • Fecha:2015-05-26
  • Categorias: Noticias Tutorial Tutorial C++

Curso De C++ - Capitulo 42 Curso De C++ - Capitulo 42...
Tutoriales en linea
¿Te gusta el tutorial?




Información
Usuarios que no esten registrados no pueden dejar comentarios, te invitamos a que te registre!






Cómo jugar Ajedrez Online TL

  • Autor:
  • Editor: Tutoriales En Linea
  • Fecha:2020-09-18
  • Categorias: WebSite Juegos Noticias Tutorial

Cómo encontrar un teléfono Android perdido

  • Autor:
  • Editor: Tutoriales En Linea
  • Fecha:2020-09-17
  • Categorias: Android Telefonia Smartphone Tablet Tutorial

Configura tu servidor VPN en Windows

  • Autor:
  • Editor: Tutoriales En Linea
  • Fecha:2020-09-15
  • Categorias: Windows Internet Red Wifi Seguridad Noticias Tutorial

Como crear una web con el lenguaje HTML

  • Autor:
  • Editor: Tutoriales En Linea
  • Fecha:2020-09-08
  • Categorias: Diseño Web Lenguajes De Programacion CSS3 html5 Html WebSite webmasters Cursos Noticias Tutorial

Introducción Al Lenguaje JS

  • Autor:
  • Editor: Tutoriales En Linea
  • Fecha:2020-09-08
  • Categorias: Diseño Web javascript Cursos Noticias Tutorial

Curso básico de Javascript

  • Autor:
  • Editor: Tutoriales En Linea
  • Fecha:2020-09-08
  • Categorias: Diseño Web javascript Cursos Noticias Tutorial