static_cast implicito dynamic_cast dev cast c++ casting language-lawyer undefined-behavior

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 ", donde B es un tipo de clase, se puede convertir a un prvalue de tipo "puntero a cv2 D ", donde D es una clase derivada (Cláusula 13) de B , 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 cv1 B " apunta a un B que en realidad es un subobjeto de un objeto de tipo D , el puntero resultante apunta al objeto circundante de tipo D 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.

[expr.reinterpret.cast]/7

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 es static_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.