Casting
static_cast()
- Static cast is used when you know the type of the object.
- It has no performance overhead.
- There are two type of casts: downcast, upcast
- Downcast:
Base*toDerived*- The compiler will tust you can do treat the pointer as a
Derived* - The program may crash if the pointer was not a
Derived*or worse could happen, i.e Undefined Behavior. You could read garbage.
- The compiler will tust you can do treat the pointer as a
- Upcast:
Derived*toBase*- This can happen implicitly, we don't need to explicitly cast it with
static_cast
- This can happen implicitly, we don't need to explicitly cast it with
- Downcast:
Common usage:
std::vector<int> data;
/**
* You gurantee that data will always fit into an int.
* If it does not, expect to see integer overflow
* This means "I know it can be represented by an int"
*/
int n = static_cast<int>(data.size());
/**
* C-style
* This is bad, this may also do a const_cast or reinterpret_cast
* This basically means "I don't care, just do it"
*/
int n = (int)data.size();
for(int i = 0; i < n; i++) {}
dynamic_cast()
- A dynamic cast is used when you're not sure what the type of the object is and you want to try-cast it.
- Typically used to downcast in polymorphic hierarchies
- Returns a
nullptrif the cast fails or throws and error if casting a reference. - Impacts performance, it checks the vtable. Depending on the polymorphic hierarchy, this could be a lot in high-performance applications.
- Safest way to cast.
- Relies on
RTTI- Run-Time Type Information: In some high-performance fields, RTTI may be disabled to improve performance.
- Dynamic cast can also cross-cast
reinterpret_cast()
- Very dangerous way to cast.
- Basically says, "take these bits and treat them like type x".
- Pure bit-reinterpretation
const_cast()
- Used to add or remove the const qualifier from a variable.
- Useful when interfacing with older APIs that aren't "const-correct."
Casting performance
| Cast | Compile-time | Runtime |
|---|---|---|
static_cast | Usually | Sometimes, e.g, for std::string, it calls the constructor |
dynamic_cast | No | Yes |
reinterpret_cast | Compile-time | Runtime behavior may be unsafe |
const_cast | Compile-time | No runtime check |
| C-style cast | Depends on what it resolves to | Depends |
static_cast may be compile time if the compiler knows exactly how to do the conversion, e.g int -> float, Base* -> Derived*
References & Citations
- Cross-Casting Mechanics:
- Hands-On Design Patterns with C++, Chapter 1, Page 16 ("Multiple Inheritance"). Fedor G. Pikus. Packt Publishing.