c++ - implicito - Lanzamiento incorrecto: ¿es el elenco o el uso el comportamiento indefinido?
static_cast c++ (2)
El elenco en sí tiene un comportamiento indefinido. Citando a C ++ 17 (n4659) [expr.static.cast] 8.2.10 / 11:
Un prvalue de tipo "puntero a cv1
B
", dondeB
es un tipo de clase, se puede convertir a un prvalue de tipo "puntero a cv2D
", dondeD
es una clase derivada (Cláusula 13) deB
, si cv2 es el la misma calificación de cv, o una mayor calificación cv que, cv1 . ... Si el prvalue de tipo "puntero a cv1B
" apunta a unB
que en realidad es un subobjeto de un objeto de tipoD
, el puntero resultante apunta al objeto circundante de tipoD
De lo contrario, el comportamiento no está definido.
Si realizo un cast desde un tipo Base a un Derived, pero el tipo Base no es una instancia de tipo derivado, pero solo uso el resultado si es así, ¿obtengo un comportamiento indefinido?
Es difícil de entender lo que estoy preguntando? Echale un vistazo a éste ejemplo:
struct Animal { int GetType(){...} };
struct Dog : Animal { bool HasLoudBark(){...}};
struct Cat : Animal { bool HasEvilStare(){...} };
Animal * a = ...;
Dog* d = static_cast<Dog*>(a);
if(a->GetType() == DogType && d->HasLoudBark())
....
En este caso, a
puede o no ser un Dog
. Siempre hacemos el static_cast
de a Dog * d
pero nunca usamos d
menos que estemos seguros de que es un Dog
.
Suponiendo que a
no es un Dog
, ¿es este comportamiento indefinido en el momento del reparto? ¿O se define como que en realidad no usamos d
menos que realmente sea un Dog
?
Se agradecen las referencias a las partes relevantes de la norma.
(Sí, sé que puedo usar dynamic_cast y RTTI, y probablemente este no sea un código excelente, pero estoy más interesado en si esto es válido)
Este es un comportamiento indefinido, pero si hubieras usado reinterpret_cast
lugar de static_cast
, static_cast
ese demonio.
Un puntero de objeto se puede convertir explícitamente a un puntero de objeto de un tipo diferente. Cuando un prvalue v del tipo de puntero de objeto se convierte en el puntero de objeto tipo "puntero a
cv T
", el resultado esstatic_cast<cv T*>(static_cast<cv void*>(v))
.
Como señaló el usuario Angew, esto "requiere una representación interna particular que garantice que static_cast<void*>(d) == static_cast<void*>(a)
when a == d
". Esos requisitos se cumplen cuando se trata de herencia simple y objetos alineados por defecto.