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; }
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; }
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; }
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; }
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; }
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; }
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