Lanzamiento incorrecto: ¿es el lanzamiento o el uso el que es un comportamiento indefinido?

Si realizo una conversión de una base a un tipo derivado, pero el tipo base no es una instancia de tipo derivado, pero solo uso el resultado si lo es, ¿obtengo un comportamiento indefinido?

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 casoa puede o no ser unDog. Siempre hacemos elstatic_cast dea aDog * d pero nunca usamosd a menos que estemos seguros de que es unDog.

Asumiendo quea no es unDog, ¿es este comportamiento indefinido en el momento del reparto? ¿O se define porque en realidad no usamosd a menos que sea realmente es unDog?

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 saber si es válido)

Respuestas a la pregunta(2)

Su respuesta a la pregunta