Dinámico _Cast en C++

C++ es un lenguaje poderoso. En C++ podemos escribir un programa estructurado y también un programa orientado a objetos . En este artículo, nos centraremos en dynamic_cast en C++. Ahora, antes de iniciar dynamic_cast en C++, primero comprenda qué es la conversión de tipos en C++ .’

Tipo de fundición :

Casting es una técnica por la cual un tipo de datos a otro tipo de datos. El operador utilizado para este propósito se conoce como operador de conversión . Es un operador unario que obliga a que un tipo de datos se convierta en otro tipo de datos. Toma el formato:

Sintaxis:

(Tipo de reparto) expresión;
              o
Tipo de conversión (expresión)

Programa 1:

C++

// C++ program to demonstrate the use
// of typecasting
#include <iostream>
using namespace std;
  
// Driver Code
int main()
{
    // Variable declaration
    int a, b;
    float c;
  
    a = 20;
    b = 40;
  
    // Typecasting
    c = (float)a * b;
  
    cout << "Result: " << c;
  
    return 0;
}
Producción:

Result: 800

Explicación: En el ejemplo anterior primero, la variable a se convierte en flotante y luego se multiplica por b , ahora el resultado también es flotante y luego el resultado se asigna a la variable c . Ahora, el valor de c es 800

Programa 2:

C++

// C++ program to read the values of two
// variables and stored the result in
// third one
#include <iostream>
using namespace std;
  
int main()
{
    // Variable declaration and
    // initialization
    int a = 7, b = 2;
    float c;
    c = a / b;
  
    cout << "Result:" << c;
  
    return 0;
}
Producción:

Result:3

Explicación: En el caso anterior, la variable c es 3 , no 3.5 , porque las variables a y b son tipos enteros, por lo tanto , a/b también es un tipo entero. Después de calcular a/b, que es de tipo int , se asigna a la variable c , que es de tipo float . Pero a/b es de tipo int , es decir, 7/2 es 3 , no 3.5 . Por lo tanto, el valor de la variable c es 3 .

Programa 3:

C++

// C++ program to read two variable value
// (a, b) and perform typecasting
#include <iostream>
using namespace std;
  
// Driver Code
int main()
{
    // Variable declaration and
    // initialization
    int a = 7, b = 2;
    float c;
  
    // Type Casting
    c = (float)a / b;
    cout << "Result :" << c;
  
    return 0;
}
Producción:

Result :3.5

Explicación: Ahora, la variable c es 3.5 , porque en la expresión anterior, primero a se convierte en flotante , por lo tanto , a/b también es de tipo flotante . 7.0/2 es 3.5 . Entonces eso se asigna a la variable c .

C++ admite cuatro tipos de conversión:

1. Elenco estático
2. Elenco dinámico
3. Elenco
constante 4. Elenco de reinterpretación

Elenco estático : este es el tipo de yeso más simple que se puede usar. Es un molde en tiempo de compilación . Hace cosas como conversiones implícitas entre tipos (como de int a float o de puntero a void*), y también puede llamar a funciones de conversión explícitas (o implícitas).

Conversión dinámica: una conversión es un operador que convierte datos de un tipo a otro tipo. En C++, la conversión dinámica se usa principalmente para la conversión segura en tiempo de ejecución. Para trabajar en dynamic_cast debe haber una función virtual en la clase base. Dynamic_cast solo funciona con una clase base polimórfica porque usa esta información para decidir una reducción segura.

Sintaxis:

dynamic_cast <nuevo_tipo>(Expresión)

  • Downcasting: La conversión de un puntero (o referencia) de clase base a un puntero (o referencia) de clase derivada se conoce como conversión a la baja. En la figura 1, conversión desde el puntero/referencia de clase base hasta el puntero/referencia de «clase 1 derivada» que muestra la conversión descendente (Base -> Clase derivada).

  • Upcasting: La conversión de un puntero (o referencia) de clase derivada a un puntero (o referencia) de clase base se conoce como conversión ascendente. En la figura 1, Casting from Derived class 2 puntero/referencia al puntero/referencia «Base class» que muestra Upcasting (Derived class 2 -> Base Class).

Como mencionamos anteriormente para la transmisión dinámica, debe haber una función virtual. Supongamos que si no usamos la función virtual, ¿cuál es el resultado?

En ese caso, genera un mensaje de error «El tipo de fuente no es polimórfico».

C++

// C++ program demonstrate if there
// is no virtual function used in
// the Base class
#include <iostream>
using namespace std;
  
// Base class declaration
class Base {
    void print()
    {
        cout << "Base" << endl;
    }
};
  
// Derived Class 1 declaration
class Derived1 : public Base {
    void print()
    {
        cout << "Derived1" << endl;
    }
};
  
// Derived class 2 declaration
class Derived2 : public Base {
    void print()
    {
        cout << "Derived2" << endl;
    }
};
  
// Driver Code
int main()
{
    Derived1 d1;
  
    // Base class pointer hold Derived1
    // class object
    Base* bp = dynamic_cast<Base*>(&d1);
  
    // Dynamic casting
    Derived2* dp2 = dynamic_cast<Derived2*>(bp);
    if (dp2 == nullptr)
        cout << "null" << endl;
  
    return 0;
}
Producción:

not null

Las funciones virtuales incluyen información de tipo de tiempo de ejecución y no hay ninguna función virtual en la clase base. Entonces este código genera un error.

Caso 1: Tomemos un ejemplo de dynamic_cast que demuestra que si la conversión es exitosa, devuelve un valor de tipo new_type .

C++

// C++ Program demonstrates successful
// dynamic casting and it returns a
// value of type new_type
#include <iostream>
  
using namespace std;
// Base Class declaration
class Base {
    virtual void print()
    {
        cout << "Base" << endl;
    }
};
  
// Derived1 class declaration
class Derived1 : public Base {
    void print()
    {
        cout << "Derived1" << endl;
    }
};
  
// Derived2 class declaration
class Derived2 : public Base {
    void print()
    {
        cout << "Derived2" << endl;
    }
};
  
// Driver Code
int main()
{
    Derived1 d1;
  
    // Base class pointer holding
    // Derived1 Class object
    Base* bp = dynamic_cast<Base*>(&d1);
  
    // Dynamic_casting
    Derived1* dp2 = dynamic_cast<Derived1*>(bp);
    if (dp2 == nullptr)
        cout << "null" << endl;
    else
        cout << "not null" << endl;
  
    return 0;
}
Producción:

not null

Explicación: En este programa, hay una clase base y dos clases derivadas (Derived1, Derived2), aquí el puntero de clase base contiene el objeto de clase 1 derivado (d1). En el momento de la clase base de transmisión dinámica , el puntero contenía el objeto Derived1 y, asignándolo a la clase derivada 1, asignó una transmisión dinámica válida . 

Caso 2: ahora, si la conversión falla y new_type es un tipo de puntero, devuelve un puntero nulo de ese tipo.

C++

// C++ Program demonstrate if the cast
// fails and new_type is a pointer type
// it returns a null pointer of that type
#include <iostream>
using namespace std;
  
// Base class declaration
class Base {
    virtual void print()
    {
        cout << "Base" << endl;
    }
};
  
// Derived1 class declaration
class Derived1 : public Base {
    void print()
    {
        cout << "Derived1" << endl;
    }
};
  
// Derived2 class declaration
class Derived2 : public Base {
    void print()
    {
        cout << "Derived2" << endl;
    }
};
  
// Driver Code
int main()
{
    Derived1 d1;
    Base* bp = dynamic_cast<Base*>(&d1);
  
    // Dynamic Casting
    Derived2* dp2 = dynamic_cast<Derived2*>(bp);
    if (dp2 == nullptr)
        cout << "null" << endl;
  
    return 0;
}
Producción:

null

Explicación: en este programa, en el momento de la conversión dinámica, el puntero de la clase base contiene el objeto Derived1 y lo asigna a la clase derivada 2, que no es una conversión dinámica válida. Entonces, devuelve un puntero nulo de ese tipo en el resultado.

Caso 3: ahora tomemos un caso más de transmisión dinámica. Si la transmisión falla y new_type es un tipo de referencia, arroja una excepción que coincide con un controlador de tipo std::bad_cast y da una advertencia: transmisión dinámica de «D1 derivado» a «clase Derived2&” nunca puede tener éxito. 

C++

// C++ Program demonstrate if the cast
// fails and new_type is a reference
// type it throws an exception
#include <exception>
#include <iostream>
using namespace std;
  
// Base class declaration
class Base {
    virtual void print()
    {
        cout << "Base" << endl;
    }
};
  
// Derived1 class
class Derived1 : public Base {
    void print()
    {
        cout << "Derived1" << endl;
    }
};
  
// Derived2 class
class Derived2 : public Base {
    void print()
    {
        cout << "Derived2" << endl;
    }
};
  
// Driver Code
int main()
{
    Derived1 d1;
    Base* bp = dynamic_cast<Base*>(&d1);
  
    // Type casting
    Derived1* dp2 = dynamic_cast<Derived1*>(bp);
    if (dp2 == nullptr)
        cout << "null" << endl;
    else
        cout << "not null" << endl;
  
    // Exception handling block
    try {
        Derived2& r1 = dynamic_cast<Derived2&>(d1);
    }
    catch (std::exception& e) {
        cout << e.what() << endl;
    }
  
    return 0;
}

Producción:

advertencia: dynamic_cast de ‘Derived1 d1’ a ‘class Derived2&’ nunca puede tener éxito Derived2& r1 = dynamic_cast<Derived2&>(d1);

Nota:

  • Un Dynamic_cast tiene una sobrecarga de tiempo de ejecución porque verifica los tipos de objetos en el tiempo de ejecución utilizando » Información de tipo de tiempo de ejecución «.
  • Si hay una garantía de que nunca enviaremos a un objeto incorrecto, entonces siempre evite el lanzamiento dinámico y use el lanzamiento estático. 
     

Publicación traducida automáticamente

Artículo escrito por varshachoudhary y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *