dynamic_cast
conversion
Safely converts pointers and references to classes up, down, and sideways along the inheritance hierarchy.
Syntax
dynamic_cast< target-type >( expression )
|
|||||||||
target-type | - | pointer to complete class type, reference to complete class type, or pointer to (optionally cv-qualified) void |
expression | - | lvalue(until C++11) glvalue(since C++11) of a complete class type if target-type is a reference, prvalue of a pointer to complete class type if target-type |
Explanation
For the convenience of description, “expression or the result is a reference to T
” means that “it is a glvalue of type T
”, which follows the convention of decltype
(since C++11)
Only the following conversions can be done with dynamic_cast, except when such conversions would cast away constness
Base
” and the type of expression is “pointer to (possibly cv-qualified) Derived
” such that Base
is a base class of Derived
, the result is
Base
” and the type of expression is “(possibly cv-qualified) Derived
” such that Base
is a base class of Derived
, the result is the unique Base
subobject of the Derived
object referred to by expression.[2]
U
”, expression must point to an object whose type is similar to U
and that is within its lifetime
U
”, expression must refer to an object whose type is similar to U
C
be the class type to which target-type points or refers. The runtime check logically executes as follows:C
object, and if only one object of type C
is derived from the subobject pointed/referred to by expression, the result points/refers to that C
object.[3]
C
, the result points/refers to the C
subobject of the most derived object.[4]
- If target-type is a pointer type, the result is the null pointer value of target-type.
- If target-type is a reference type, an exception of a type that would match a handler of type std::bad_cast
When dynamic_cast is used in a constructor or a destructor (directly or indirectly), and expression refers to the object that's currently under construction/destruction, the object is considered to be the most derived object. If target-type
- ↑ In other words, dynamic_cast can be used to add constness. An implicit conversion and static_cast
- ↑ 2.0 2.1 An implicit conversion and static_cast can perform this conversion as well.
- ↑ This is known as a “downcast”.
- ↑ This is known as a “sidecast”.
Similar to other cast expressions, the result is:
|
(until C++11) |
|
(since C++11) |
Notes
A downcast can also be performed with static_cast, which avoids the cost of the runtime check, but it is only safe if the program can guarantee (through some other logic) that the object pointed to by expression is definitely Derived
Some forms of dynamic_cast rely on run-time type identification
Keywords
Example
#include <iostream> struct V { virtual void f() {} // must be polymorphic to use runtime-checked dynamic_cast }; struct A : virtual V {}; struct B : virtual V { B(V* v, A* a) { // casts during construction (see the call in the constructor of D below) dynamic_cast<B*>(v); // well-defined: v of type V*, V base of B, results in B* dynamic_cast<B*>(a); // undefined behavior: a has type A*, A not a base of B } }; struct D : A, B { D() : B(static_cast<A*>(this), this) {} }; struct Base { virtual ~Base() {} }; struct Derived : Base { virtual void name() {} }; int main() { D d; // the most derived object A& a = d; // upcast, dynamic_cast may be used, but unnecessary [[maybe_unused]] D& new_d = dynamic_cast<D&>(a); // downcast [[maybe_unused]] B& new_b = dynamic_cast<B&>(a); // sidecast Base* b1 = new Base; if (Derived* d = dynamic_cast<Derived*>(b1); d != nullptr) { std::cout << "downcast from b1 to d successful\n"; d->name(); // safe to call } Base* b2 = new Derived; if (Derived* d = dynamic_cast<Derived*>(b2); d != nullptr) { std::cout << "downcast from b2 to d successful\n"; d->name(); // safe to call } delete b1; delete b2; }
Output:
downcast from b2 to d successful
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 1269 | C++11 | the runtime check was not performed for xvalue expression s if target-type is an rvalue reference type |
performed |
CWG 2861 | C++98 | expression could point/refer to a type-inaccessible object | the behavior is undefined in this case |
References
- C++23 standard (ISO/IEC 14882:2024):
- 7.6.1.7 Dynamic cast [expr.dynamic.cast]
- C++20 standard (ISO/IEC 14882:2020):
- 7.6.1.6 Dynamic cast [expr.dynamic.cast]
- C++17 standard (ISO/IEC 14882:2017):
- 8.2.7 Dynamic cast [expr.dynamic.cast]
- C++14 standard (ISO/IEC 14882:2014):
- 5.2.7 Dynamic cast [expr.dynamic.cast]
- C++11 standard (ISO/IEC 14882:2011):
- 5.2.7 Dynamic cast [expr.dynamic.cast]
- C++98 standard (ISO/IEC 14882:1998):
- 5.2.7 Dynamic cast [expr.dynamic.cast]
- C++03 standard (ISO/IEC 14882:2003):
- 5.2.7 Dynamic cast [expr.dynamic.cast]