2010-02-27 23 views
12

He estado leyendo mucho sobre la fundición C++ y estoy empezando a confundirse porque siempre he utilizado la fundición de estilo C.confusa en C++ fundición

He leído que C fundición estilo debe ser evitado en C++ y que reinterpret_cast es muy, muy peligroso y no debe ser usado cada vez que hay una alternativa. Al contrario de no usar reinterpret_cast, lo he visto usado muchas veces en MSDN en su código de muestra. Esto me lleva a hacer mi primera pregunta, ¿cuándo está bien usar reinterpret_cast?

Por ejemplo:

LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) 
{ 
    switch (Msg) 
    { 
     case WM_CREATE: 
     { 
      LPCREATESTRUCT lpCreateStruct = reinterpret_cast<LPCREATESTRUCT>(lParam); 
      return 0; 
     } 
    } 

    ... 
} 

Si eso no es aceptable, entonces ¿cómo iba a emitir el valor lParam a un puntero utilizando solamente estática, dinámica y/o const casting?

También: Si reinterpret_cast no es portátil, ¿cómo iba a volver a escribir que sea portátil (para una buena práctica)

+1

Esto podría ser MUY código antiguo base. –

Respuesta

8

Usando reinterpret_cast es aceptable si sabe que el puntero era originalmente del tipo de destino. Cualquier otro uso es aprovechar el comportamiento dependiente de la implementación, aunque en muchos casos esto es necesario y útil, como convertir un puntero a una estructura en un puntero a bytes para que pueda ser serializado.

Se considera peligroso ya que no realiza comprobaciones, ya sea en tiempo de compilación o en tiempo de ejecución. Si comete un error, puede y se bloqueará y se quemará horriblemente, y será difícil de depurar. Básicamente le estás diciendo al compilador: "Sé mejor que tú lo que es esto en realidad, así que compila el código y déjame preocuparme por las consecuencias".

+1

Serializar las estructuras de esa manera es una mala idea (incluso si se hace muy a menudo), pero ese es un tema para otra pregunta. – Tronic

5

La razón por la que ves en MSDN se debe a la API de Win32 es una API C , pero la gente insiste en dar ejemplos en C++ .

reinterpretar elenco está bien cuando estás escribiendo código que interactúa con otras bibliotecas. Debe evitarse dentro de su propia aplicación.

2

No es una falta de respeto de MSDN, pero MSDN no es el mejor lugar para ir para la correcta codificación de C++.

Una razón para utilizar reinterpret_cast es cuando se está lanzando a/de los tipos de datos opacos. reinterpret_cast no es "peligroso", es solo que es fácil arruinarlo y provocar problemas en el código, por lo que debe evitarse.

La razón por la que se prefieren los modelos de C++ es que static_cast es seguro, y todos los tiempos de lanzamiento son más fáciles de buscar.

programadores [incorrectamente] menudo utilizan moldes a "rem advertencias del compilador", tales como la conversión de unsigned a enteros con signo, o de un número entero de 32 bits a una de 8 bits uno.

+1

+1. MSDN está repleto de MS-ismos. Los buenos libros de Scott Meyers y Herb Sutter (aunque ahora está en MS, es un excelente escritor y tiene muchos buenos consejos para escribir buenos C++) son mejores lugares para consolidar la comprensión de la buena práctica de C++. –

+0

@Matt Curtis: encuentro que la parte más molesta de MSDN es que los MS-ismos se aplican de forma inconsistente. La calidad varía mucho con sus ejemplos. En términos generales, sin embargo, no debe copiar y pegar sus ejemplos; puede darle una idea aproximada, pero debe adaptar esas ideas al estilo de codificación que se use en el proyecto en el que está trabajando. – asveikau

2

Esencialmente reinterpret_cast es "segura" con las estructuras C y los tipos básicos (dejando al descubierto los errores de civil como echar int a un puntero y la espalda, que trabaja en la arquitectura ILP32 pero se rompe en una LP64.) Estructura de CA no tiene nada en ella , excepto el posible relleno para la alineación, que no declaraste.

reinterpret_cast no es seguro con tipos polimórficos C++ desde el compilador inserta elementos de datos en su clase - cosas como punteros a tablas virtuales y punteros a clases base virtuales. Otros modelos de C++ se encargan de ajustarlos cuando, por ejemplo, lanzar de puntero a clase base a puntero a clase derivada, reinterpret_cast y los moldes de estilo C no.

3

Este es un ejemplo de programación de Windows Platform SDK, una API C, con C++. El procedimiento de ventana solo tiene los parámetros WPARAM y LPARAM y si necesita pasar un puntero a una estructura a través de un mensaje de ventana, tiene que ser emitido. Este es un uso perfectamente aceptable de reinterpret_cast <> en mi opinión. No puede evitar un elenco porque el SDK en el que está escribiendo, que no es su código, no fue diseñado para C++, y mucho menos para la seguridad de tipos, y necesita que el molde proporcione tipos de parámetros genéricos con un enlace de C.

reinterpret_cast <> aquí hay una bandera que le permite saber que debe tener cuidado, pero no debe evitarse a toda costa.

Si, por otro lado, usted controla ambas partes del código, la API y el consumidor, sería mejor hacer una API que fuera segura y no requiriera que el consumidor realice moldes para usarla correctamente.

Cuestiones relacionadas