There are four main forms of cast in C++:
static_cast
, dynamic_cast
, const_cast
and reinterpret_cast
. This article explores when and how you should use each.Static Cast
This is the most commonly used form of cast. It is used to convert between ordinary types. For instance, converting
int
to float
or vice versa.A common use case of
static_cast
would be if you needed to pass a certain primitive type to a function, but your variables are of the wrong type.void myFunction(double x) { ... } int x = 3; // x is stored as int myFunction(static_cast<double>(x)); // static_cast x to double
This form of casting is heavily preferred over traditional C style of casting:
myFunction((double)x); // C style of casting myFunction(static_cast<double>(x)); // Cpp style of casting
There are two main reasons for this.
- 1.
static_cast
adds a compile time check for our casts. In the example below we try to cast a dynamically allocated into to achar*
, which does not makes sense. Line 1 will compile, while line 2 will not compile.
char* c = (char*)new int( 3 ); //(1) char* c1 = static_cast<char*>( new int( 3 ) ); //(2)
- 2. It is much easier to search
static_cast
in your code.
Dynamic Cast
Unlike
static_cast
, dynamic_cast
involves runtime checking. At runtime, it will safely cast pointers/references up/down/sideways in your inheritance heirarchy. A failed cast on a pointer type will return a nullptr
and a failed cast on a reference type will throw an std::bad_cast
exception.This cast only works on polymorphic types: any class with at least one virtual method/destructor/base class.
This cast is commonly used in polymorphic situations in which you have a pointer/reference to a base class, but you would like to perform a derived class operation.
static_cast
can also be used in these scenarios, but they will not provide the same runtime checks.class Base { public: virtual ~Base() {} }; class Derived : public Base {}; Base *base = new Derived; Derived *derived = dynamic_cast<Derived*>(base);
Const Cast
This cast is used to remove the constness of a variable. For instance, it can be used to cast away the const in a const pointer so that it can be passed into a function that does not accept a const pointer.
If you modify a value that is initially declared const, the output will be undefined. That is, if
void someFunction(SomeObject *obj)
modifies obj
, then we will have undefined behavior.void someFunction(SomeObject *obj) { ... } const SomeObject *const_ptr = createConstObjectPtr(); SomeObject *ptr = const_cast<SomeObject*>(obj); someFunction(ptr);
Reinterpret Cast
Reinterpret cast can be used to reinterpret the type of a variable. It is generally used to cast a pointer of one type to another type regardless of the relation between the two types.
int* p = new int(65); char* ch = reinterpret_cast<char*>(p);
Summary
static_cast
-> convert between ordinary typesdynamic_cast
-> use for polymorphic typesconst_cast
-> cast away constreinterpret_cast
->reinterpret the typeSources: