Conversión de tipo explícita
Convierte entre tipos utilizando una combinación de conversiones explícitas e implícitas.
Contenido |
[editar] Sintaxis
( tipo-de-destino ) expresión
|
(1) | ||||||||
tipo-de-destino ( lista-de-expresiones (opcional) )
|
(2) | ||||||||
tipo-de-destino { lista-de-expresiones (opcional) }
|
(3) | (desde C++11) | |||||||
nombre-de-plantilla ( lista-de-expresiones (opcional) )
|
(4) | (desde C++17) | |||||||
nombre-de-plantilla { lista-de-expresiones (opcional) }
|
(5) | (desde C++17) | |||||||
auto ( expresión )
|
(6) | (desde C++23) | |||||||
auto { expresión }
|
(7) | (desde C++23) | |||||||
Devuelve un valor de tipo tipo-de-destino.
[editar] Explicación
const_cast
<tipo-de-destino>(expresión);static_cast
<tipo-de-destino>(expresión), con extensiones: se permite además convertir un puntero o referencia a una clase derivada a un puntero o referencia a una clase base inequívoca (y viceversa) incluso si la clase base es inaccesible (es decir, esta conversión ignora el especificador de herencia privada). Lo mismo se aplica a la conversión de puntero a miembro a un puntero a miembro de una base no virtual inequívoca;reinterpret_cast
<tipo-de-destino>(expresión);- Si hay exactamente una expresión entre paréntesis, esta expresión de conversión es exactamente equivalente a la expresión de estilo de conversión C correspondiente.
- Si hay más de una expresión o inicialización de lista entre llaves (desde C++11) entre paréntesis, tipo-de-destino debe ser una clase con un constructor declarado adecuadamente. Esta expresión es un pr-valor de tipo tipo-de-destino que designa un objeto temporal (hasta C++17)cuyo objeto resultado es (desde C++17) inicializado mediante inicialización directa con
(
expresión-list)
como inicializador. - Si no hay expresión entre paréntesis: si tipo-de-destino nombra un tipo objeto array no completo, esta expresión es un pr-valor de tipo tipo-de-destino, que designa un (hasta C++17)temporal (desde C++17) cuyo objeto resultado es (posiblemente con calificadores agregados const volatile) de ese tipo. Si tipo-de-destino es un tipo objeto, el objeto es inicializado por valor. Si tipo-de-destino es (posiblemente calificado const volatile) void, la expresión es un pr-valor void sin un objeto resultado (desde C++17).
{
expresión-list }
como inicializador. Si tipo-de-destino es (posiblemente calificado const volatile) void, la expresión es un void pr-valor without a result object (desde C++17).
Esta es la única expresión de conversión que puede crear un array de tipo pr-valor. (hasta C++20)auto
se reemplaza con el tipo deducido de expresión. El resultado siempre es un pr-valor de un tipo objeto.Como con todas las expresiones de conversión, el resultado es:
- Un l-valor si tipo-de-destino es un tipo referencia a l-valor o un tipo referencia r-valor a función (desde C++11);
|
(desde C++11) |
- Un pr-valor en caso contrario.
[editar] Resolución de ambigüedades
[editar] Instrucción de declaración ambigua
En el caso de una ambigüedad entre una declaración de expresión con una expresión de conversión de estilo función como su subexpresión más a la izquierda y una declaración, la ambigüedad se resuelve tratándola como una declaración. Esta desambiguación es puramente sintáctica: no considera el significado de los nombres que aparecen en la declaración, salvo si son nombres de tipo:
struct M {}; struct L { L(M&); }; M n; void f() { M(m); // declaración, equivalente a M m; L(n); // declaración mal formada, equivalente a L n; L(l)(m); // todavía una declaración, equivalente a L l((m)); }
Sin embargo, si el declarador más externo en la instrucción de declaración ambigua tiene un tipo de retorno al final, la instrucción solo se tratará como una declaración si el tipo de retorno final comienza con auto: struct M; struct S { S* operator()(); int N; int M; void mem(S s) { auto(s)()->M; // expresión (S::M hides ::M), inválida antes de C++23 } }; void f(S s) { { auto(s)()->N; // expresión, inválida antes de C++23 auto(s)()->M; // declaración de función, equivalente a M s(); } { S(s)()->N; // expresión S(s)()->M; // expresión } } |
(desde C++11) |
[editar] Parámetro de función ambiguo
La ambigüedad anterior también puede ocurrir en el contexto de una declaración. En ese contexto, la elección es entre una declaración de objeto con una función de estilo de conversión como inicializador y una declaración que involucra un declarador de función con un conjunto redundante de paréntesis alrededor de un nombre de parámetro. La solución también es considerar cualquier construcción, como la posible declaración de parámetro, que podría ser una declaración como tal:
struct S { S(int); }; void foo(double a) { S w(int(a)); // declaración de función: tiene un parámetro `a` de tipo int S x(int()); // declaración de función: tiene un parámetro sin nombre de tipo int(*)() // que se ajusta desde int() // Formas de evitar ambigüedad: S y((int(a))); // declaración de objeto: extra par de paréntesis S y((int)a); // declaración de objeto: conversión estilo C S z = int(a); // declaración de objeto: no hay ambigüedad para esta sintaxis }
Sin embargo, si el declarador más externo en la declaración de parámetro ambiguo tiene un tipo de retorno al final, la ambigüedad solo se resolverá tratándolo como una declaración si comienza con auto: typedef struct BB { int C[2]; } *B, C; void foo() { S a(B()->C); // declaración de objeto: B()->C no puede declarar un parámetro S b(auto()->C); // declaración de función: tiene un parámetro sin nombre de tipo C(*)() // que está ajustado de C() } |
(desde C++11) |
[editar] id-de-tipo ambiguo
Una ambigüedad puede surgir de la similitud entre una conversión de estilo de función y un id-de-tipo. La solución es que cualquier construcción que podría ser un id-de-tipo en su contexto sintáctico se considerará un id-de-tipo:
// `int()` y `int(unsigned(a))` pueden analizarse como id-de-tipo: // `int()` representa una función que devuelve int // y no toma argumentos // `int(unsigned(a))` representa una función que devuelve int // y toma un argumento de tipo unsigned void foo(signed char a) { sizeof(int()); // id-de-tipo (mal formado) sizeof(int(a)); // expresión sizeof(int(unsigned(a))); // id-de-tipo (mal formado) (int()) + 1; // id-de-tipo (mal formado) (int(a)) + 1; // expresión (int(unsigned(a))) + 1; // id-de-tipo (mal formado) }
Sin embargo, si el declarador-abstracto más externo en el id-de-tipo ambiguo tiene un tipo de retorno al final, la ambigüedad solo se resolverá tratándolo como un id-de-tipo si comienza con auto: typedef struct BB { int C[2]; } *B, C; void foo() { sizeof(B()->C[1]); // OK, sizeof(expresión) sizeof(auto()->C[1]); // ERROR: sizeof de una función que devuelve un array } |
(desde C++11) |
[editar] Notas
Macro de prueba de característica | Valor | Estándar | Comentario |
---|---|---|---|
__cpp_auto_cast |
202110L | (C++23) | auto(x) y auto{x} |
[editar] Ejemplo
#include <cassert> #include <iostream> double f = 3.14; unsigned int n1 = (unsigned int)f; // conversión estilo C unsigned int n2 = unsigned(f); // conversión estilo función class C1; class C2; C2* foo(C1* p) { return (C2*)p; // convierte un tipo incompleto a otro tipo incompleto } void cpp23_decay_copy_demo() { auto inc_print = [](int& x, const int& y) { ++x; std::cout << "x:" << x << ", y:" << y << '\n'; }; int p{1}; inc_print(p, p); // imprime x:2 y:2, porque el parámetro `y` aquí es un alias de `p` int q{1}; inc_print(q, auto{q}); // imprime x:2 y:1, auto{q} (C++23) convierte a pr-valor, // entonces el parámetro `y` es una copia de `q` (no un alias de `q`) } // En este ejemplo, la conversión estilo C se interpreta como static_cast // aunque funcionaría como reinterpret_cast struct A {}; struct I1 : A {}; struct I2 : A {}; struct D : I1, I2 {}; int main() { D* d = nullptr; // A* a = (A*)d; // error en tiempo de compilación A* a = reinterpret_cast<A*>(d); // esto compila assert(a == nullptr); cpp23_decay_copy_demo(); }
Salida:
x:2 y:2 x:2 y:1
[editar] Informes de defectos
Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.
ID | Aplicado a | Comportamiento según lo publicado | Comportamiento correcto |
---|---|---|---|
P2915R0 | C++11 | La adición del tipo de retorno al final introdujo más ambigüedades. | Las resuelve. |
CWG 2620 | C++98 | La resolución de parámetros de función ambiguos podría ser malinterpretada. | Se mejoró la redacción. |
CWG 2828 | C++98 | Una conversión estilo C estaba mal formada si existen múltiples interpretaciones de un static_cast seguido de un const_cast, independientemente de si estas conversiones se usan realmente. |
Solo considera las conversiones posiblemente en uso. |
[editar] Referencias
- El estándar C++23 (ISO/IEC 14882:2023):
- 7.6.1.4 Conversión de tipo explícita (notación funcional) [expr.type.conv]
- 7.6.3 Conversión de tipo explícita (notación de conversión) [expr.cast]
- El estándar C++20 (ISO/IEC 14882:2020):
- 7.6.1.4 Conversión de tipo explícita (notación funcional) [expr.type.conv]
- 7.6.3 Conversión de tipo explícita (notación de conversión) [expr.cast]
- El estándar C++17 (ISO/IEC 14882:2017):
- 8.2.3 Conversión de tipo explícita (notación funcional) [expr.type.conv]
- 8.4 Conversión de tipo explícita (notación de conversión) [expr.cast]
- El estándar C++14 (ISO/IEC 14882:2014):
- 5.2.3 Conversión de tipo explícita (notación funcional) [expr.type.conv]
- 5.4 Conversión de tipo explícita (notación de conversión) [expr.cast]
- El estándar C++11 (ISO/IEC 14882:2011):
- 5.2.3 Conversión de tipo explícita (notación funcional) [expr.type.conv]
- 5.4 Conversión de tipo explícita (notación de conversión) [expr.cast]
- El estándar C++03 (ISO/IEC 14882:2003):
- 5.2.3 Conversión de tipo explícita (notación funcional) [expr.type.conv]
- 5.4 Conversión de tipo explícita (notación de conversión) [expr.cast]
- El estándar C++98 (ISO/IEC 14882:1998):
- 5.2.3 Conversión de tipo explícita (notación funcional) [expr.type.conv]
- 5.4 Conversión de tipo explícita (notación de conversión) [expr.cast]
[editar] Véase también
const_cast conversión | agrega o quita const
Original: adds or removes const The text has been machine-translated via Google Translate. You can help to correct and verify the translation. Click here for instructions. |
static_cast conversión | realiza conversiones básicas
Original: performs basic conversions The text has been machine-translated via Google Translate. You can help to correct and verify the translation. Click here for instructions. |
dynamic_cast conversión | realiza conversiones marcadas polimórficos
Original: performs checked polymorphic conversions The text has been machine-translated via Google Translate. You can help to correct and verify the translation. Click here for instructions. |
reinterpret_cast conversión | realiza en general de bajo nivel conversiones
Original: performs general low-level conversions The text has been machine-translated via Google Translate. You can help to correct and verify the translation. Click here for instructions. |
conversiones estándar | conversiones implícitas de un tipo a otro
Original: implicit conversions from one type to another The text has been machine-translated via Google Translate. You can help to correct and verify the translation. Click here for instructions. |
Documentación de C para cast operator
|