Typically used to cast away the constness of objects. It is the only C++ style that can do this.
reinterpret_cast
Converts any pointer type to any other pointer type, even of unrelated classes. The operation result is a simple binary copy of the value from one pointer to the other.
Intended for low-level casts that yield implementation-dependent and it would not be portable.
Let’s consider an example:
So reinterpret_cast just read 1st and 2nd bytes of value and wrote it into a and b. It treats variable value of type int as a variable of type struct Data.
Another way of using reinterpret_cast is to compare pointers.
Here is an example:
a == &c == true - c is implicitly casted to A class, so a and casted c are identical. reinterpret_cast<char*>(a) == reinterpret_cast<char*>(&c) == true - treats a and &c as pointers to char, the 1st byte is the same in both pointers. b == &c == true - c is implicitly casted to B class, so b and casted c are identical.
reinterpret_cast<char*>(b) == reinterpret_cast<char*>(&c) == false - after upcasting b kind of points at part of c which has offset of sizeof(A). reinterpret_cast<char*>(a) == reinterpret_cast<char*>(b) == false - after upcasting a points at the beginning of the c and b at part of c which has offset of sizeof(A).
Output of the last string is:
Adress of c = 000000E77974F664
a = 000000E77974F664
b = 000000E77974F665
static_cast
Valid only for related objects(base, derived). Can be used for upcasting (child->base) for objects/pointers. Downcasting for objects won’t compile as it is incorrect, but for pointers it will but child’s members will contain garbage.
dynamic_cast
This kind of cast is used to perform safe downcasting, i.e., to determine whether an object is of a particular type in an inheritance hierarchy. It is the only cast that may have a significant runtime cost.
dynamic_cast involves a run-time type check. If the object bound to the pointer is not an object of the target type, it fails and the value is 0. If it’s a reference type when it fails, then an exception of type bad_cast is thrown. So, if we want dynamic_cast to throw an exception (bad_cast) instead of returning 0, cast to a reference instead of to a pointer. Note also that the dynamic_cast is the only cast that relies on run-time checking.
A use case example:
DoSomething(Window* w) is passed down Window pointer. It calls scroll() method which is only available from Scroll object. So, in this case, we need to check if the object is the Scroll type or not before the call to the scroll() method.
Example (static_cast/dynamic_cast):
In both cases the result is Woof, because bark() is treated as a static function.
Change bark() to void bark() { std::cout << "Woof\n" << a; }then bark() won’t be static anymore and sydog->bark() prints Woof + some garbage because Dog doesn’t have the field int a and dydog->bark() will trow an exception because of the access through nullptr.
It’s better not to use static_cast here and instead use dynamic_cast but first check that upcasting performed correctly: