Casting in C++
18 April, 2013 - 3 min read
static_cast
static_cast
is used for cases where you basically want to reverse an implicit conversion, with a few restrictions and additions. static_cast
performs no runtime checks. This should be used if you know that you refer to an object of a specific type, and thus a check would be unnecessary. Example:
void func(void *data) {
// conversion from MyClass* -> void* is implicit
MyClass *c = static_cast<MyClass*>(data);
...
}
int main() {
MyClass c;
start_thread(&func, &c) // func(&c) will be called
.join();
}
In this example, you know that you passed a MyClass
object, and thus there is no need for a runtime check to ensure this.
dynamic_cast
dynamic_cast
is used for cases where you don't know what the dynamic type of the object is. You cannot use dynamic_cast
if you downcast and the argument type is not polymorphic. An example
if(JumpStm *j = dynamic_cast<JumpStm*>(&stm)) {
...
} else if(ExprStm *e = dynamic_cast<ExprStm*>(&stm)) {
...
}
dynamic_cast
returns a null pointer if the object referred to doesn't contain the type casted to as a base class (when you cast to a reference, a bad_cast
exception is thrown in that case).
The following code is not valid, because Base
is not polymorphic (doesn't contain a virtual function):
struct Base { };
struct Derived : Base { };
int main() {
Derived d; Base *b = &d;
dynamic_cast<Derived*>(b); // invalid
}
An "up-cast" is always valid with both static_cast
and dynamic_cast
, and also without any cast, as an "up-cast" is an implicit conversion.
Regular Cast
These casts are also called c-style cast. A c-style cast is basically identical to trying out a range of sequences of C++ casts, and taking the first c++ cast that works, without ever consideringdynamic_cast
. Needless to say that this is much more powerful as it combines all of const_cast
,static_cast
and reinterpret_cast
, but it's also unsafe because it does not usedynamic_cast
.
In addition, C-style casts not only allow you to do this, but also allow you to safely cast to a private base-class, while the "equivalent" static_cast
sequence would give you a compile time error for that.
Some people prefer c-style casts because of their brevity. I use them for numeric casts only, and use the appropriate C++ casts when user defined types are involved, as they provide stricter checking.
const_cast conversion | adds or removes const |
static_cast conversion | performs basic conversions |
dynamic_cast conversion | performs checked polymorphic conversions |
reinterpret_cast conversion | performs general low-level conversions |
standard conversions | implicit conversions from one type to another |
END