Приведение
В C++, если класс является производным от базового класса, содержащего одну или несколько виртуальных функций, можно использовать указатель на этот тип базового класса для вызова виртуальных функций в производном объекте класса. Класс, содержащий виртуальные функции, иногда называется "полиморфным".
Иерархия классов
Объект типа C
можно визуализировать следующим образом:
Класс C с вложенными объектами B и A
При наличии экземпляра класса C
есть B
подобъект и A
подобъект. Экземпляр C
, содержащий подчиненные объекты A
и B
, является "полным объектом".
Так как производный класс полностью содержит определения всех базовых классов, производных от которых он является производным, он безопасно приведения указателя на любой из его базовых классов (также называемый переадресацией). Если указатель на базовый класс, он может быть безопасным для приведения указателя к экземпляру производного класса (также называемого даунт-рассылкой).
С помощью сведений о типе времени выполнения можно проверить, указывает ли указатель на полный объект и может быть безопасно приведение к другому объекту в иерархии. Оператор dynamic_cast выполняет проверку во время выполнения, чтобы убедиться, что операция безопасна. Лучше разработать иерархию классов, чтобы можно было использовать виртуальные функции, чтобы избежать необходимости переадресовки. Тем не менее, если необходимо переадресовать, используйте для dynamic_cast
обеспечения безопасности операции.
Для преобразования неполиморфных типов можно использовать оператор static_cast (в этом разделе объясняется различие между статическими и динамическими преобразованиями приведения, а также при необходимости их использования).
В следующем примере показано использование dynamic_cast
и static_cast
:
#include <iostream>
class Base {
public:
virtual void print() { std::cout << "Base\n"; }
};
class Derived1 : public Base {
public:
void print() override { std::cout << "Derived1\n"; }
};
class Derived2 : public Base {
public:
void print() override { std::cout << "Derived2\n"; }
};
class MostDerived : public Derived1, public Derived2 {
public:
void print() override { std::cout << "MostDerived\n"; }
};
int main() {
MostDerived md;
Base* b1 = static_cast<Derived1*>(&md); // Upcast to Derived1 is safe
Base* b2 = static_cast<Derived2*>(&md); // Upcast to Derived2 is safe
// Downcast to MostDerived is ambiguous and unsafe
// MostDerived* md1 = static_cast<MostDerived*>(b1); // This won't compile
// MostDerived* md2 = static_cast<MostDerived*>(b2); // This won't compile
// Correct way to downcast in this situation
MostDerived* md1 = dynamic_cast<MostDerived*>(b1); // This is safe
MostDerived* md2 = dynamic_cast<MostDerived*>(b2); // This is safe
md1->print(); // Prints "MostDerived"
md2->print(); // Prints "MostDerived"
return 0;
}
В этом разделе описываются следующие темы:
См. также
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по