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