What Is dynamic_cast in C++?
Purpose
- Safely convert between polymorphic types at runtime
- Commonly used to downcast from a base class to a derived class
- Performs a runtime type check using RTTI (Run-Time Type Information)
Basic Syntax
Derived* d = dynamic_cast<Derived*>(basePtr);
- If
basePtrpoints to an actualDerivedobject, the cast succeeds - If not, the result is
nullptr
When It Fails
- Pointer cast: returns
nullptrif the actual type is not the target - Reference cast: throws
std::bad_caston failure
Pointer Downcast Example
class Entity {
virtual ~Entity() {}
};
class Player : public Entity {};
class Enemy : public Entity {};
Entity* e = new Enemy;
Player* p = dynamic_cast<Player*>(e);
if (p) {
// safe to use p
} else {
// p is nullptr
}
Reference Downcast Example
try {
Entity& e_ref = *new Enemy;
Player& p_ref = dynamic_cast<Player&>(e_ref);
} catch (const std::bad_cast& ex) {
// handle the error
}
Derived to Base Cast (Upcasting)
- Always safe and allowed
- Implicit — no cast needed
- Does not require
dynamic_cast
Upcasting Example
class Entity {
virtual void say() {}
};
class Player : public Entity {
void jump() {}
};
Player p;
Entity* e = &p; // implicit upcast — always safe
e->say(); // OK
// e->jump(); // error: jump is not in Entity
Requirements for dynamic_cast
- The base class must be polymorphic (have at least one
virtualfunction) - The cast must involve pointers or references
- RTTI must be enabled (default in most compilers)
Comparison: static_cast vs dynamic_cast
| Feature | static_cast |
dynamic_cast |
|---|---|---|
| Compile-time check | ✅ | ❌ |
| Runtime safety | ❌ | ✅ |
| Can return nullptr or throw | ❌ (undefined behavior if wrong) | ✅ |
| Requires virtual function in base? | ❌ | ✅ |
Summary
- Use
dynamic_castfor type-safe downcasting when dealing with polymorphic base classes - Always check for
nullptr(pointer) or catchstd::bad_cast(reference) - Use implicit or
static_castfor upcasting (derived to base) — it’s always safe
C/C++ Programming
- Understanding std::transform_reduce in Modern C++
- Implement a Lock Acquire and Release in C++
- Detecting Compile-time vs Runtime in C++: if consteval vs std::is_constant_evaluated()
- C++ Forward References: The Key to Perfect Forwarding
- Understanding dynamic_cast in C++: Safe Downcasting Explained
- C vs C++: Understanding the restrict Keyword and its Role in Optimization
- C++ Lvalue, Rvalue and Rvalue References
- C++ assert vs static_assert
- Why auto_ptr is Deprecated in C++?
- C++ What is the consteval? How is it different to const and constexpr?
- Tutorial on C++ std::move (Transfer Ownership)
- const vs constexpr in C++
- Tutorial on C++ Ranges
- Tutorial on C++ Smart Pointers
- Tutorial on C++ Future, Async and Promise
- The Memory Manager in C/C++: Heap vs Stack
- The String Memory Comparision Function memcmp() in C/C++
- Modern C++ Language Features
- Comparisions of push_back() and emplace_back() in C++ std::vector
- C++ Coding Reference: is_sorted_until() and is_sorted()
- C++ Coding Reference: iota() Setting Incrementing Values to Arrays or Vectors
- C++ Coding Reference: next_permutation() and prev_permutation()
- C++ Coding Reference: count() and count_if()
- C++ Code Reference: std::accumulate() and Examples
- C++ Coding Reference: sort() and stable_sort()
- The Next Permutation Algorithm in C++ std::next_permutation()
–EOF (The Ultimate Computing & Technology Blog) —
550 wordsLast Post: Monitoring 28 VPS Machines (Including a Raspberry Pi) with Nezha Dashboard
Next Post: Turning a Dusty Raspberry Pi into a Home Server for Blockchain Monitoring