c++ conversion tipos - ¿Cuándo deben utilizarse static_cast, dynamic_cast, const_cast y reinterpret_cast?





3 Answers

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

Utilice static_cast para conversiones de tipo ordinario.

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

Use const_cast para desechar const/volatile . Evita esto a menos que estés atascado usando una API const-incorrect.

datos ejemplo casteo

¿Cuáles son los usos adecuados de:

  • static_cast
  • dynamic_cast
  • const_cast
  • reinterpret_cast
  • (type)value C (estilo (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?




Podría ayudar si sabes un poco de partes internas ...

static_cast

  • El compilador de C ++ ya sabe cómo convertir tipos de escaladores, como float a int. Usa static_cast para ellos.
  • En el caso general de la conversión de tipo A a B , static_cast llama al constructor de B pasa A como parámetro. Si B no tiene dicho constructor, obtienes un error de tiempo de compilación.
  • La conversión de A* a B* siempre tiene éxito si A y B están en jerarquía de herencia (o nula), de lo contrario, se produce un error de compilación.
  • Gotcha : Si lanza el puntero de base al puntero derivado pero si el objeto real no es realmente un tipo derivado, entonces no obtiene el error. Obtienes un mal puntero y un error de seguridad en tiempo de ejecución. Lo mismo ocurre con A& to B& .
  • Gotcha : ¡Reparto de Derivado a Base o viceversa crea una nueva copia! Para las personas que vienen de C # / Java, esto puede ser una gran sorpresa.

dynamic_cast

  • dynamic_cast utiliza información de tipo de tiempo de ejecución para averiguar si la conversión es válida. Por ejemplo, (Base*) a (Derived*) puede fallar si el puntero no es realmente del 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& to B& si el lanzamiento no es válido, dynamic_cast lanzará la excepción bad_cast.
  • A diferencia de otros lanzamientos, hay una sobrecarga de tiempo de ejecución.

const_cast

  • Si bien static_cast puede hacer constantes, no puede ir de otra manera. El const_cast puede hacer ambas formas.
  • Un ejemplo en el que esto es útil es iterar a través de algún contenedor como el set<T> que solo devuelve sus elementos como const para asegurarse de que no cambie su clave. Sin embargo, si su intención es modificar los miembros no clave del objeto, entonces debería estar bien. Puedes usar const_cast para eliminar 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.

reinterpretar_cast

  • Básicamente, esto dice que tome estos bytes en esta ubicación de memoria y piense en él 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.



Además de las otras respuestas hasta ahora, aquí hay un ejemplo obvio donde static_cast no es suficiente para que se necesite reinterpret_cast . Supongamos que hay una función que en un parámetro de salida devuelve los punteros a objetos de diferentes clases (que no comparten una clase base común). Un ejemplo real de dicha función es CoCreateInstance() (ver el último parámetro, que de hecho es void** ). Supongamos que solicita una clase particular de objeto de esta función, por lo que sabe de antemano el tipo para el puntero (que a menudo hace para los objetos COM). En este caso, no puede lanzar el puntero a su 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 puede reescribirse 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);



Related