[c++] ¿Cuándo se deberían usar static_cast, dynamic_cast, const_cast y reinterpret_cast?



2 Answers

Use dynamic_cast para convertir punteros / referencias dentro de una jerarquía de herencia.

Use static_cast para las conversiones de tipo ordinario.

Utilice reinterpret_cast para la reinterpret_cast de bajo nivel de patrones de bits. Usar con extrema precaución.

Usa const_cast para descartar const/volatile . Evita esto a menos que estés atascado con una API incorrecta.

Question

¿Cuáles son los usos apropiados de:

  • static_cast
  • dynamic_cast
  • const_cast
  • reinterpret_cast
  • (type)value conversión de (type)value C (type)value
  • type(value) conversión de estilo de función type(value)

¿Cómo se decide cuál usar en qué casos específicos?




Además de las otras respuestas hasta ahora, este es un ejemplo obvio en el que static_cast no es suficiente para que reinterpret_cast sea ​​necesario. Supongamos que hay una función que en un parámetro de salida devuelve punteros a objetos de diferentes clases (que no comparten una clase base común). Un ejemplo real de tal función es CoCreateInstance() (vea el último parámetro, que de hecho es void** ). Supongamos que solicita una clase particular de objeto a partir de esta función, para que sepa de antemano el tipo de puntero (que a menudo hace para los objetos COM). En este caso, no puede convertir el puntero al puntero en void** con static_cast : necesita reinterpret_cast<void**>(&yourPointer) .

En codigo:

#include <windows.h>
#include <netfw.h>
.....
INetFwPolicy2* pNetFwPolicy2 = nullptr;
HRESULT hr = CoCreateInstance(__uuidof(NetFwPolicy2), nullptr,
    CLSCTX_INPROC_SERVER, __uuidof(INetFwPolicy2),
    //static_cast<void**>(&pNetFwPolicy2) would give a compile error
    reinterpret_cast<void**>(&pNetFwPolicy2) );

Sin embargo, static_cast funciona para punteros simples (no punteros a punteros), por lo que el código anterior se puede reescribir para evitar reinterpret_cast (a un precio de una variable adicional) de la siguiente manera:

#include <windows.h>
#include <netfw.h>
.....
INetFwPolicy2* pNetFwPolicy2 = nullptr;
void* tmp = nullptr;
HRESULT hr = CoCreateInstance(__uuidof(NetFwPolicy2), nullptr,
    CLSCTX_INPROC_SERVER, __uuidof(INetFwPolicy2),
    &tmp );
pNetFwPolicy2 = static_cast<INetFwPolicy2*>(tmp);



Podría ayudar si conoces un poco de internos ...

static_cast

  • El compilador de C ++ ya sabe cómo convertir tipos de scaler como float a int. Usa static_cast para ellos.
  • En general, al convertir el tipo A a B, static_cast llamaría al constructor de B pasándolo A. Si B no tiene dicho constructor, entonces obtendrá un error de tiempo de compilación.
  • Transmitir de A* a B* siempre tiene éxito si A y B están en la jerarquía de herencia (o nulo), de lo contrario se obtiene un error de compilación.
  • Gotcha : Si lanzas el puntero base al puntero derivado, pero si el objeto real es si no es un tipo derivado, entonces no obtienes ningún error. Obtiene un puntero malo y, tan pronto como intenta acceder a los miembros del puntero derivado, obtiene segfault en el tiempo de ejecución.
  • Lo mismo vale para A& B& .
  • Gotcha : ¡Transmitido de Derivado a Base o viceversa crea una nueva copia! Para las personas que vienen de C # / Java, muchos de los anteriores pueden ser una gran sorpresa.

dynamic_cast

  • dynamic_cast usa información del tipo de tiempo de ejecución para determinar si el cast es válido. Por ejemplo, (Base*) a (Derived*) puede fallar si el puntero no es en realidad de tipo derivado.
  • Esto significa que dynamic_cast es muy caro en comparación con static_cast.
  • Para A* a B* , si el lanzamiento no es válido, dynamic_cast devolverá nullptr.
  • Para A& B& si el lanzamiento no es válido, dynamic_cast arrojará la excepción bad_cast.

const_cast

  • Mientras static_cast puede hacer no-const para const no puede ir en sentido contrario. El const_cast puede hacer las dos cosas.
  • Un ejemplo donde esto es útil es iterar a través de un contenedor como set<T> que solo devuelve sus elementos como const para asegurarse de no cambiar su clave. Sin embargo, si su intención es modificar los miembros no clave del objeto, entonces debería estar bien. Puede usar const_cast para eliminar la constness.
  • Otro ejemplo es cuando desea implementar T& foo() así como const T& foo() . Para evitar la duplicación de código, puede aplicar const_cast para devolver el valor de una función de otra.
  • A diferencia de los dos lanzamientos anteriores, hay sobrecarga en tiempo de ejecución.

reinterpretar_cast

  • Esto básicamente dice que tome estos bytes en esta ubicación de memoria y piense en ello como un objeto dado.
  • Por ejemplo, puede cargar 4 bytes de float a 4 bytes de int para ver cómo se ven los bits en float.
  • Obviamente, si los datos no son correctos para el tipo, puede obtener segfault.
  • No hay sobrecarga de tiempo de ejecución para este elenco.



Related