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
e
can be converted from an implicit type toT
- If a standard conversion sequence exists for types from
T
toe
, 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
e
toT
involves left-to-right, array-to-pointer, function-to-pointer conversions, this can be done explicitly via static type conversion - if
T
is 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
T
is a right-valued reference type ande
is 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
T
ande
is 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
void
can 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
e
andT
are of identical type, orT
is more constant thane
, a dynamic type conversion ofe
toT
can be performed (static_cast
is also possible) - if the expression
e
is a zero pointer value (nullptr
), you can convert to a zero pointer ofT
- if
T
is a pointer or reference to a base class, the expressione
is 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_cast
can do the same) - if the expression
e
is polymorphic andT
is a pointer tovoid
, the dynamic type conversion converts it to the most derived pointer - If the expression
e
is a pointer or reference to a polymorphic base class andT
is 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 typeT
can be obtained frome
, then the conversion can be performed successfully (downcast) - if
e
itself 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
e
is the objectthis
being constructed, then the object is considered to be the most derived object, and the behavior is undefined ifT
is 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.