If I do a cast from a Base to a Derived type, but the Base type isn't an instance of derived type, but only use the result if it is, do I get undefined behaviour?
Hard to understand what I'm asking? take a look at this example:
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()) ....
In this case a
may or not be a Dog
. We always do the static_cast
of a
to Dog * d
but we never use d
unless we're sure its a Dog
.
Assuming that a
is not a Dog
, is this undefined behaviour at the point of the cast? Or is it defined as we don't actually use d
unless it is really is a Dog
?
References to the relevant parts of the standard are appreciated.
(Yes I know I can use dynamic_cast, and RTTI, and probably this isn't great code, but I'm more interested in whether this is valid)
According to the C standards, signed integer overflow is undefined behaviour too. A few compilers may trap the overflow condition when compiled with some trap handling options, while a few compilers simply ignore the overflow conditions (assuming that the overflow will never happen) and generate the code accordingly.
Undefined behavior exists mainly to give the compiler freedom to optimize. One thing it allows the compiler to do, for example, is to operate under the assumption that certain things can't happen (without having to first prove that they can't happen, which would often be very difficult or impossible).
The cast itself has undefined behaviour. Quoting C++17 (n4659) [expr.static.cast] 8.2.10/11:
A prvalue of type “pointer to cv1
B
”, whereB
is a class type, can be converted to a prvalue of type “pointer to cv2D
”, whereD
is a class derived (Clause 13) fromB
, if cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. ... If the prvalue of type “pointer to cv1B
” points to aB
that is actually a subobject of an object of typeD
, the resulting pointer points to the enclosing object of typeD
. Otherwise, the behavior is undefined.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With