Static_cast vs dynamic_cast vs reinterpret_cast in C++: Key Differences
static_cast performs compile-time checked conversions between related types, dynamic_cast safely converts polymorphic types at runtime with type checking, and reinterpret_cast performs low-level, unsafe conversions that simply reinterpret the bit pattern of a pointer or reference.Quick Comparison
Here is a quick table summarizing the main differences between static_cast, dynamic_cast, and reinterpret_cast in C++.
| Feature | static_cast | dynamic_cast | reinterpret_cast |
|---|---|---|---|
| Purpose | Convert related types safely at compile time | Convert polymorphic types safely at runtime | Low-level cast, reinterprets bits without safety |
| Type Checking | Compile-time | Runtime with RTTI | None |
| Use Case | Conversions like int to float, base to derived (if safe) | Downcasting in class hierarchies with virtual functions | Pointer conversions, type punning |
| Safety | Safe if used correctly | Safe, returns nullptr or throws on failure | Unsafe, can cause undefined behavior |
| Performance | Fast, no runtime overhead | Slower, involves runtime checks | Fast, no checks |
| Requires Polymorphism | No | Yes | No |
Key Differences
static_cast is used for conversions between related types known at compile time, such as numeric conversions or up/down casting in inheritance when you are sure about the types. It does not check types at runtime, so misuse can cause undefined behavior.
dynamic_cast is designed for safe downcasting in polymorphic class hierarchies. It uses runtime type information (RTTI) to check if the cast is valid. If the cast fails, it returns nullptr for pointers or throws an exception for references, preventing unsafe conversions.
reinterpret_cast is the most low-level cast. It simply reinterprets the bit pattern of one type as another without any safety checks. It is used for pointer conversions or type punning but can easily cause undefined behavior if misused. It does not require polymorphism or related types.
Code Comparison
This example shows how static_cast converts a base class pointer to a derived class pointer when the cast is safe.
#include <iostream> class Base { public: virtual void speak() { std::cout << "Base speaking\n"; } }; class Derived : public Base { public: void speak() override { std::cout << "Derived speaking\n"; } void derivedOnly() { std::cout << "Derived only function\n"; } }; int main() { Base* basePtr = new Derived(); Derived* derivedPtr = static_cast<Derived*>(basePtr); // Safe because basePtr actually points to Derived derivedPtr->speak(); derivedPtr->derivedOnly(); delete basePtr; return 0; }
dynamic_cast Equivalent
This example uses dynamic_cast to safely downcast a base class pointer to a derived class pointer with runtime checking.
#include <iostream> class Base { public: virtual void speak() { std::cout << "Base speaking\n"; } virtual ~Base() = default; }; class Derived : public Base { public: void speak() override { std::cout << "Derived speaking\n"; } void derivedOnly() { std::cout << "Derived only function\n"; } }; int main() { Base* basePtr = new Base(); Derived* derivedPtr = dynamic_cast<Derived*>(basePtr); // Will be nullptr because basePtr is not Derived if (derivedPtr) { derivedPtr->speak(); derivedPtr->derivedOnly(); } else { std::cout << "dynamic_cast failed: basePtr is not a Derived\n"; } delete basePtr; return 0; }
When to Use Which
Choose static_cast when you know the types are related and the conversion is safe at compile time, such as numeric conversions or upcasting/downcasting without polymorphic checks.
Choose dynamic_cast when you need safe downcasting in polymorphic class hierarchies and want runtime type checking to avoid invalid casts.
Choose reinterpret_cast only for low-level operations like converting between unrelated pointer types or type punning, and be very careful because it can easily cause undefined behavior.
Key Takeaways
static_cast is for compile-time checked conversions between related types.dynamic_cast safely casts polymorphic types at runtime using RTTI.reinterpret_cast reinterprets bits without safety and should be used cautiously.dynamic_cast for safe downcasting in class hierarchies with virtual functions.reinterpret_cast unless you have a specific low-level need.