Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incorrect cast - is it the cast or the use which is undefined behavior

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)

like image 685
Mike Vine Avatar asked Apr 23 '18 12:04

Mike Vine


People also ask

What type of behavior C is undefined?

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.

Why does undefined behavior exist?

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).


1 Answers

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”, where B is a class type, can be converted to a prvalue of type “pointer to cv2 D”, where D is a class derived (Clause 13) from B, if cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. ... If the prvalue of type “pointer to cv1 B” points to a B that is actually a subobject of an object of type D, the resulting pointer points to the enclosing object of type D. Otherwise, the behavior is undefined.

like image 195
Angew is no longer proud of SO Avatar answered Sep 21 '22 15:09

Angew is no longer proud of SO