Ось пробіг на static_cast<>таdynamic_cast<> конкретно, коли вони стосуються покажчиків. Це просто 101 рівень рівня, він не охоплює всіх тонкощів.
static_cast <Тип *> (ptr)
Це забирає вказівник ptrі намагається безпечно передати його на тип вказівника Type*. Цей склад виконується під час компіляції. Він буде виконувати роль лише у тому випадку, якщо типи типів пов'язані між собою. Якщо типи не пов'язані, ви отримаєте помилку компілятора. Наприклад:
class B {};
class D : public B {};
class X {};
int main()
{
D* d = new D;
B* b = static_cast<B*>(d); // this works
X* x = static_cast<X*>(d); // ERROR - Won't compile
return 0;
}
динамічний_кас <Тип *> (ptr)
Це знову намагається взяти вказівник ptrі безпечно віддати його до вказівника типу Type*. Але цей виступ виконується під час виконання, а не час компіляції. Оскільки це кастинг під час виконання, він корисний особливо в поєднанні з поліморфними класами. Насправді в сертифікованих випадках класи повинні бути поліморфними, щоб акторський склад був законним.
У ролях можуть йти в одному з двох напрямків: від базового до похідного (B2D) або від похідного до базового (D2B). Це досить просто, щоб побачити, як касти D2B працюватимуть під час виконання. Або ptrбуло похідне, Typeабо його не було. У випадку з D2B dynamic_cast <> s, правила прості. Ви можете спробувати кинути що завгодно на що-небудь інше, і якщо ptrнасправді було похідне Type, ви отримаєте Type*вказівник назад dynamic_cast. В іншому випадку ви отримаєте вказівник NULL.
Але бродіння B2D трохи складніше. Розглянемо наступний код:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void DoIt() = 0; // pure virtual
virtual ~Base() {};
};
class Foo : public Base
{
public:
virtual void DoIt() { cout << "Foo"; };
void FooIt() { cout << "Fooing It..."; }
};
class Bar : public Base
{
public :
virtual void DoIt() { cout << "Bar"; }
void BarIt() { cout << "baring It..."; }
};
Base* CreateRandom()
{
if( (rand()%2) == 0 )
return new Foo;
else
return new Bar;
}
int main()
{
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();
base->DoIt();
Bar* bar = (Bar*)base;
bar->BarIt();
}
return 0;
}
main()не можу сказати, який тип об’єкта CreateRandom()повернеться, тому актерський стиль у Bar* bar = (Bar*)base;форматі C , очевидно, не є безпечним для типу. Як ви могли це виправити? Одним із способів було б додати таку функцію, як bool, AreYouABar() const = 0;до базового класу та повернутись trueіз Barта falseз Foo. Але є й інший спосіб: use dynamic_cast<>:
int main()
{
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();
base->DoIt();
Bar* bar = dynamic_cast<Bar*>(base);
Foo* foo = dynamic_cast<Foo*>(base);
if( bar )
bar->BarIt();
if( foo )
foo->FooIt();
}
return 0;
}
Касти виконуються під час виконання та працюють, запитуючи об’єкт (не потрібно турбуватися про те, як зараз), запитуючи його, чи це той тип, який ми шукаємо. Якщо він є, dynamic_cast<Type*>повертає вказівник; в іншому випадку він повертає NULL.
Щоб цей кастинг з базовим походженням працював dynamic_cast<>, Base, Foo і Bar повинні бути тими, що Стандарт називає поліморфними типами . Для того, щоб бути поліморфним типом, ваш клас повинен мати принаймні одну virtualфункцію. Якщо ваші класи не є поліморфними типами, використання на основі «похідних dynamic_cast» не буде складено. Приклад:
class Base {};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // ERROR - Won't compile
return 0;
}
Додавання до бази віртуальної функції, наприклад, віртуального dtor, призведе до поліморфних типів Base та Der:
class Base
{
public:
virtual ~Base(){};
};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // OK
return 0;
}
dynamic_cast<>працює за лаштунками (або скільки C ++ працює), гарною книгою (що також досить легко читати для чогось такого технічного) є "Внутрішня об'єктна модель C ++" Ліппмена. Також книги "Структура та еволюція C ++" та "Мова програмування на C ++" Струструпа є хорошими ресурсами, але книга Ліппмана присвячена тому, як C ++ працює "за кадром".