dynamic_cast преобразование
Безопасно преобразует указатели и ссылки на классы вверх, вниз и вбок по иерархии наследования.
Синтаксис
dynamic_cast< target-type >( expression ) |
| target-type | - | указатель на полный тип класса, ссылка на полный тип класса или указатель на void (с необязательными квалификаторами cv) |
| expression | - | lvalue(до C++11)glvalue(начиная с C++11) полного типа класса, если target-type является ссылкой; prvalue указательного типа на полный тип класса, если target-type является указателем |
Пояснение
Для удобства описания выражение «expression или результат является ссылкой на T» означает, что «это glvalue типа T», что соответствует соглашению, используемому в decltype(начиная с C++11).
С помощью dynamic_cast можно выполнять только следующие преобразования, кроме случаев, когда такие преобразования приводят к снятию константности (или волатильности).
Base (с возможными квалификаторами cv)», а тип expression — «указатель на Derived (с возможными квалификаторами cv)», причем Base является базовым классом Derived, результатом будет - нулевое значение указателя, если expression имеет нулевое значение указателя, или
- указатель на единственный подобъект
BaseобъектаDerived, на который указывает expression, в противном случае. Иными словами, dynamic_cast можно использовать для приведения вверх указателей от производного класса к базовому. Это преобразование также можно выполнить с помощью неявного преобразования и static_cast.
Base (с возможными квалификаторами cv)», а тип expression — «Derived (с возможными квалификаторами cv)», причем Base является базовым классом Derived, результатом будет единственный подобъект Base объекта Derived, на который ссылается expression. Иными словами, dynamic_cast можно использовать для приведения вверх ссылок от производного класса к базовому. Это преобразование также можно выполнить с помощью неявного преобразования и static_cast.Target, на который указывает или на который ссылается target-type:Target и от подобъекта, на который указывает или на который ссылается expression, производен только один объект типа Target, результат указывает на этот объект Target. Иными словами, dynamic_cast можно использовать для приведения вниз указателей и ссылок от базового класса к производному.Target, результат указывает на подобъект Target наиболее производного объекта. Иными словами, dynamic_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 | Применяется к | Опубликованное поведение | Правильное поведение |
|---|---|---|---|
| CWG 1269 | C++11 | проверка во время выполнения не выполнялась для xvalue expression ов, если 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]
См. также
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/dynamic_cast