dynamic_cast
conversion
Безопасно преобразует указатели и ссылки на классы вверх, вниз и вбок по иерархии наследования.
Содержание |
Синтаксис
dynamic_cast<
target-type
>(
expression
)
|
|||||||||
| target-type | - | указатель на полный тип класса, ссылка на полный тип класса, или указатель на (опционально cv-квалифицированный) void |
| expression | - | lvalue (until C++11) glvalue (since C++11) полного типа класса, если target-type является ссылкой, prvalue указателя на полный тип класса, если target-type является указателем |
Объяснение
Для удобства описания, «
expression
или результат является ссылкой на
T
» означает, что «это glvalue типа
T
»
, что соответствует соглашению
decltype
(since C++11)
.
Только следующие преобразования могут быть выполнены с помощью dynamic_cast , за исключением случаев, когда такие преобразования снимают константность (или volatile-квалификатор).
Base
" и тип
expression
является "указателем на (возможно cv-квалифицированный)
Derived
" таким образом, что
Base
является базовым классом
Derived
, результатом будет
- нулевое значение указателя, если expression является нулевым указателем, или
-
указатель на уникальный
Baseподобъект объектаDerived, на который указывает expression в противном случае. Другими словами, dynamic_cast может использоваться для повышающего преобразования указателей, от производного к базовому. Неявное преобразование и static_cast также могут выполнять это преобразование.
Base
», а тип
expression
— «(возможно cv-квалифицированный)
Derived
», причём
Base
является базовым классом для
Derived
, результатом будет уникальный
Base
подобъект объекта
Derived
, на который ссылается
expression
. Другими словами,
dynamic_cast
может использоваться для
upcast
ссылок — от производного класса к базовому. Неявное преобразование и
static_cast
также могут выполнять это преобразование.
Target
, на который указывает или на который ссылается
target-type
:
Target
, и если только один объект типа
Target
является производным от подобъекта, на который указывает/на который ссылается
expression
, результат указывает/ссылается на этот объект
Target
. Другими словами,
dynamic_cast
может использоваться для
понижающего преобразования
указателей/ссылок, от базового к производному.
Target
, результат указывает/ссылается на подобъект
Target
наиболее производного объекта. Другими словами,
dynamic_cast
может использоваться для
кросс-каста
(или side-cast) указателей/ссылок между двумя типами, производными от одного базового класса.
- Если target-type является типом указателя, результатом будет нулевое значение указателя типа target-type .
- Если target-type является ссылочным типом, выбрасывается исключение типа, соответствующего обработчику типа std::bad_cast .
Когда dynamic_cast используется в конструкторе или деструкторе (напрямую или косвенно), и expression ссылается на объект, который в настоящее время конструируется/уничтожается, этот объект считается наиболее производным объектом. Если target-type не является указателем или ссылкой на собственный класс конструктора/деструктора или один из его базовых классов, поведение не определено.
Аналогично другим выражениям приведения типов, результат следующий:
|
(до C++11) |
|
(начиная с C++11) |
Примечания
Приведение к производному типу также может быть выполнено с помощью
static_cast
, что позволяет избежать затрат на проверку во время выполнения, но это безопасно только если программа может гарантировать (с помощью другой логики), что объект, на который указывает
expression
, точно является
Derived
.
Некоторые формы dynamic_cast зависят от идентификации типов во время выполнения (RTTI), то есть информации о каждом полиморфном классе в скомпилированной программе. Компиляторы обычно имеют опции для отключения включения этой информации.
Ключевые слова
Пример
#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; }
Вывод:
downcast from b2 to d successful
Отчёты о дефектах
Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены задним числом к ранее опубликованным стандартам C++.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| CWG 1269 | C++11 |
проверка во время выполнения не выполнялась для xvalue
expression s если target-type является типом rvalue-ссылки |
выполняется |
| CWG 2861 | C++98 | expression мог указывать/ссылаться на объект с недоступным типом | поведение в этом случае не определено |
Ссылки
- Стандарт C++23 (ISO/IEC 14882:2024):
-
- 7.6.1.7 Динамическое приведение типов [expr.dynamic.cast]
- Стандарт C++20 (ISO/IEC 14882:2020):
-
- 7.6.1.6 Динамическое приведение типа [expr.dynamic.cast]
- Стандарт C++17 (ISO/IEC 14882:2017):
-
- 8.2.7 Динамическое приведение типов [expr.dynamic.cast]
- Стандарт C++14 (ISO/IEC 14882:2014):
-
- 5.2.7 Динамическое приведение типа [expr.dynamic.cast]
- Стандарт C++11 (ISO/IEC 14882:2011):
-
- 5.2.7 Динамическое приведение типов [expr.dynamic.cast]
- Стандарт C++98 (ISO/IEC 14882:1998):
-
- 5.2.7 Динамическое приведение типа [expr.dynamic.cast]
- Стандарт C++03 (ISO/IEC 14882:2003):
-
- 5.2.7 Динамическое приведение типа [expr.dynamic.cast]