Introduction
This blog is about the four type conversions in C++: static_cast, const_cast, reinterpret_cast, const_cast, their usage and some usage scenarios.
static_cast
The reference scenario of static_cast compares conversions, according to CppReference, to perform static type conversions from the expression e to T in the following cases.
Common types
- for the expression
ecan be converted from an implicit type toT - If a standard conversion sequence exists for types from
Ttoe, a static type conversion can perform the inverse of that implicit type conversion sequence. This conversion does not include: left-value to right-value, array to pointer, function to pointer conversions - if the conversion from
etoTinvolves left-to-right, array-to-pointer, function-to-pointer conversions, this can be done explicitly via static type conversion - if
Tis of typevoid, the static type conversion will discard the value of the expressione
Some examples are shown below.
|
|
- Enumeration types
- scoped enumerations can be converted to integer or floating point types
- the value of an enum or integer can be converted to any full enum type
Some examples are shown below.
|
|
- Reference types
- if type
Tis a right-valued reference type andeis an object, a static type conversion converts it to a would-be value of the same type, for examplestd::move.
- if type
- (unsafe) Pointer types containing conversions between inheritance relations
- if a reference or pointer of type
Tandeis a left-valued or purely right-valued pointer to its base classB, a down-conversion (base class to derived class) is possible, no guarantee that there is really a derived class variable in that memory location - a pointer to a member variable of derived class D can be upconverted to a pointer to its base class B without guaranteeing the existence of the member in the base class
- a pointer to
voidcan be converted to a pointer to any object type
- if a reference or pointer of type
Some examples of unsafe use are shown below.
|
|
As you can see that conversions involving inheritance relationships between static types are not safe because static types are only compile-time checked and may lead to unclear behavior at runtime if they pass compile-time checking. Therefore for this type of conversion it is better to use dynamic type conversion.
dynamic_cast
dynamic_cast can implement upward, downward or sideways conversions of pointers or references on inheritance relationships. According to CppReference, there are the following cases where a dynamic type conversion can be performed.
- if the expression
eandTare of identical type, orTis more constant thane, a dynamic type conversion ofetoTcan be performed (static_castis also possible) - if the expression
eis a zero pointer value (nullptr), you can convert to a zero pointer ofT - if
Tis a pointer or reference to a base class, the expressioneis a pointer and reference to a derived class and the base class is unique. Dynamic type conversion converts the base class component of the derived class object to a pointer to the base class object (implicit type conversion andstatic_castcan do the same) - if the expression
eis polymorphic andTis a pointer tovoid, the dynamic type conversion converts it to the most derived pointer - If the expression
eis a pointer or reference to a polymorphic base class andTis a pointer to a derived class, the dynamic type conversion will perform a runtime check:- check the derived hierarchy of the object referred to by
e, if the typeTcan be obtained frome, then the conversion can be performed successfully (downcast) - if
eitself is not of a type at one level of the derived hierarchy, but the object it refers to is the most derived type, then it can be converted toT(sidecast, see example below)
- check the derived hierarchy of the object referred to by
- If dynamic type conversion is used directly or indirectly in a constructor or destructor, if
eis the objectthisbeing constructed, then the object is considered to be the most derived object, and the behavior is undefined ifTis not the type of the object itself or its base class.
The following are some examples.
|
|
dynamic_cast is mainly used to convert a dynamic base class pointer to a derived class pointer. Since diamond inheritance is rarely used in projects, side-cast cases are rare.
reinterpret_cast
reinterpret_cast can perform conversions between any pointer variables, and is generally used less often. The scenario can be used when there is some per-bit information flow, when packing and decompressing data. As the following example shows, we convert a data type to a generic data type with reinterpret_cast, and then somehow get the data and reconvert it to the data type we need.
|
|
const_cast
const_cast can be used to remove constancy from a type and is not recommended in general.