¿Cuál es la diferencia entre static_cast <> y la conversión de estilo C?


Respuestas:


217

El compilador verifica los moldes de estilo C ++. Los modelos de estilo C no son y pueden fallar en tiempo de ejecución.

Además, los moldes de estilo c ++ se pueden buscar fácilmente, mientras que es realmente difícil buscar moldes de estilo c ++.

Otro gran beneficio es que los 4 modelos diferentes de estilo C ++ expresan la intención del programador más claramente.

Cuando escribo C ++, casi siempre uso los de C ++ sobre el estilo de C.


67
Los únicos lanzamientos que pueden fallar en tiempo de ejecución son dynamic_casts.
R. Martinho Fernandes

12
C ++ reinterpret_cast <T> (U) puede fallar en tiempo de ejecución casi de la misma manera que los lanzamientos de estilo C, y todos son bastante diferentes de cómo falla dynamic_cast <T> (U).
Christopher Smith

20
Cast1 el lanzamiento normal de C (int)somethingno puede fallar, ya sea que reciba el int o el error del compilador.
Tomáš Zato - Restablece a Mónica el

2
¿Puedes explicar por qué los moldes C ++ se pueden buscar más fácilmente que los moldes C?
Minh Tran

3
@MinhTran Para el estilo C ++ puede buscar la palabra clave "cast" a través de sus archivos fuente. Pero, ¿qué podrías hacer con los moldes estilo c?
huangzonghao

176

En resumen :

  1. static_cast<>() le da una capacidad de comprobación de tiempo de compilación, el elenco de C-Style no.
  2. static_cast<>() es más legible y se puede detectar fácilmente en cualquier lugar dentro de un código fuente de C ++, C_Style cast is'nt.
  3. Las intenciones se transmiten mucho mejor usando moldes C ++.

Más explicaciones :

La conversión estática realiza conversiones entre tipos compatibles . Es similar al elenco de estilo C, pero es más restrictivo. Por ejemplo, el reparto de estilo C permitiría que un puntero entero apunte a un carácter.

char c = 10;       // 1 byte
int *p = (int*)&c; // 4 bytes

Como esto da como resultado un puntero de 4 bytes (un puntero al tipo de datos de 4 bytes) que apunta a 1 byte de memoria asignada, escribir en este puntero causará un error de tiempo de ejecución o sobrescribirá alguna memoria adyacente.

*p = 5; // run-time error: stack corruption

A diferencia de la conversión de estilo C, la conversión estática permitirá que el compilador verifique que los tipos de datos de puntero y puntero sean compatibles, lo que permite al programador detectar esta asignación de puntero incorrecta durante la compilación.

int *q = static_cast<int*>(&c); // compile-time error

También puede consultar esta página para obtener más explicaciones sobre los moldes de C ++: haga clic aquí


17
Creo que en lugar de "puntero de 4 bytes"
querías

pero permite int q = static_cast <int> (c);
TonyParker

3
@TonyParker Eso es porque no hay nada de malo en esa línea.
Braden Best

15

Consulte una comparación de los operadores de conversión de C ++ .

Sin embargo, el uso de la misma sintaxis para una variedad de operaciones de conversión diferentes puede hacer que la intención del programador no sea clara.

Además, puede ser difícil encontrar un tipo específico de conversión en una base de código grande.

La generalidad del elenco de estilo C puede ser exagerada para situaciones donde todo lo que se necesita es una simple conversión. La capacidad de seleccionar entre varios operadores de fundición diferentes de diferentes grados de potencia puede evitar que los programadores emitan inadvertidamente a un tipo incorrecto.


14
struct A {};
struct B : A {};
struct C {}; 

int main()
{
    A* a = new A;    

    int i = 10;

    a = (A*) (&i); // NO ERROR! FAIL!

    //a = static_cast<A*>(&i); ERROR! SMART!

    A* b = new B;

    B* b2 = static_cast<B*>(b); // NO ERROR! SMART!

    C* c = (C*)(b); // NO ERROR! FAIL!

    //C* c = static_cast<C*>(b); ERROR! SMART!
}

55
¿Podría por favor elaborar más su respuesta agregando un poco más de descripción sobre la solución que proporciona?
abarisone

1
Creo que la respuesta muestra que "static_casts" verifica las conversiones de tipos para asegurarse de que estén en rutas válidas en el gráfico de jerarquía. En este ejemplo particular, se permite la conversión de A * a B * o B * a A * porque A y B forman una ruta en el gráfico jerárquico. C * no está en la ruta, por lo que static_cast producirá un error en tiempo de compilación. Nota al margen: puede valer la pena señalar que la conversión de A * a B * puede dar como resultado NULL con un Dynamic_cast en tiempo de ejecución, dependiendo del verdadero objeto subyacente.
Tommy Chen

7

Una gran publicación que explica diferentes moldes en C / C ++, y lo que realmente hace el elenco de estilo C: https://anteru.net/blog/2007/12/18/200/index.html

C-Style casting, utilizando la sintaxis variable (tipo). Lo peor jamás inventado. Esto intenta hacer los siguientes lanzamientos, en este orden: (ver también C ++ Standard, 5.4 expr.cast, párrafo 5)

  1. const_cast
  2. static_cast
  3. static_cast seguido de const_cast
  4. reinterpret_cast
  5. reinterpret_cast seguido de const_cast

5

static_castcomprueba en tiempo de compilación que la conversión no es entre tipos obviamente incompatibles. Al contrario dynamic_cast, no se verifica la compatibilidad de tipos en tiempo de ejecución. Además, la static_castconversión no es necesariamente segura.

static_cast se utiliza para convertir de puntero a clase base a puntero a clase derivada, o entre tipos nativos, como enum a int o float a int.

El usuario de static_castdebe asegurarse de que la conversión sea segura.

El elenco de estilo C no realiza ninguna comprobación, ni en la compilación ni en el tiempo de ejecución.


3

Dado que hay muchos tipos diferentes de conversión, cada uno con una semántica diferente, static_cast <> le permite decir "Estoy haciendo una conversión legal de un tipo a otro", como de int a double. Un elenco simple de estilo C puede significar muchas cosas. ¿Estás subiendo / bajando? ¿Estás reinterpretando un puntero?

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.