Un operador Cast es un operador unario que obliga a que un tipo de datos se convierta en otro tipo de datos.
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 una conversión de tiempo de compilación . Hace cosas como conversiones implícitas entre tipos (como int a float o pointer a void*), y también puede llamar a funciones de conversión explícitas (o implícitas).
Por ejemplo
#include <iostream> using namespace std; int main() { float f = 3.5; int a = f; // this is how you do in C int b = static_cast<int>(f); cout << b; }
Producción:
3
Ahora hagamos algunos cambios en el código.
#include <iostream> using namespace std; int main() { int a = 10; char c = 'a'; // pass at compile time, may fail at run time int* q = (int*)&c; int* p = static_cast<int*>(&c); return 0; }
Si compila el código, obtendrá un error:
[Error] invalid static_cast from type 'char*' to type 'int*'
Esto significa que incluso si cree que puede encasillar un objeto en particular en otro pero es ilegal , static_cast no le permitirá hacer esto.
Tomemos otro ejemplo de conversión de objetos hacia y desde una clase.
#include <iostream> #include <string> using namespace std; class Int { int x; public: Int(int x_in = 0) : x{ x_in } { cout << "Conversion Ctor called" << endl; } operator string() { cout << "Conversion Operator" << endl; return to_string(x); } }; int main() { Int obj(3); string str = obj; obj = 20; string str2 = static_cast<string>(obj); obj = static_cast<Int>(30); return 0; }
Ejecute el código anterior:
Conversion Ctor called Conversion Operator Conversion Ctor called Conversion Operator Conversion Ctor called
Intentemos entender el resultado anterior:
- Cuando se crea obj , se llama al constructor, que en nuestro caso también es un constructor de conversión (para C++ 14, las reglas cambian un poco).
- Cuando crea str a partir de obj , el compilador no arrojará un error ya que hemos definido el operador de conversión.
- Cuando haces
obj=20
, en realidad estás llamando al constructor de conversión. - Cuando haces str2 a partir de static_cast , es bastante similar a
string str=obj;
, pero con una verificación de tipos estricta. - Cuando escribes
obj=static_cast<Int>(30)
, estás convirtiendo 30 en Int usando static_cast.
Tomemos un ejemplo que implica herencia.
#include <iostream> using namespace std; class Base { }; class Derived : public Base { }; int main() { Derived d1; Base* b1 = (Base*)(&d1); // allowed Base* b2 = static_cast<Base*>(&d1); return 0; }
El código anterior se compilará sin ningún error.
- Tomamos la dirección
d1
y la convertimos explícitamenteBase
y la almacenamos enb1
. - Tomamos la dirección
d1
y usamos static_cast para convertirloBase
y almacenarlo enb2
.
Como sabemos, static_cast realiza una verificación estricta de tipos, veamos un poco el código modificado para verlo:
#include <iostream> using namespace std; class Base { }; class Derived : private Base { // Inherited private/protected not public }; int main() { Derived d1; Base* b1 = (Base*)(&d1); // allowed Base* b2 = static_cast<Base*>(&d1); return 0; }
Intenta compilar el código anterior, ¿Qué ves? ¡¡¡¡¡¡¡Error de compilación!!!!!!!
[Error] 'Base' is an inaccessible base of 'Derived'
El código anterior no se compilará incluso si lo heredas como protected . Entonces, para usar static_cast, heredélo como público.
Use static_cast para lanzar el puntero vacío ‘hacia y desde’.
#include <iostream> int main() { int i = 10; void* v = static_cast<void*>(&i); int* ip = static_cast<int*>(v); return 0; }