# Семинар 6 ## RTTI - Run Time Type Identification - typeid - dynamic_cast ### typeid > `typeid` возвращает тип объекта/указателя. Если указатель на класс с виртуальными функциями, вернёт именно тип объекта. Иначе - указателя. Для `type_info` переопределённые операции и методы: - == - !- - .name ```cpp class A { public: virtual void f() {} }; class B : public A {}; int main () { A *pa = new B; B *pb; std::cout << typeid(*pa).name; // 1B (1 символ в имени) if (typeid(*pa) == typeid(B)) { pb = (B*)pa; // небезопасное приведение } } ``` ## Dynamic cast ```cpp class A { public: virtual void f() {} }; class B : public A {}; int main () { A *pa, a; B *pb, b; pa = &b; // безопасно приводит, вернёт не NULL в случае успеха pb = dynamic_cast(pa); } ``` ```cpp class A { public: virtual void f() {} }; class B : public A {}; int main () { A *pa, a; B *pb, b; A &pr = a; // B &rb = dynamic_cast(pa); // выкинет bad_cast } ``` ## Исключения `try - throw - catch` `terminate()` - в случае, если ничего не обработалось приводится в `catch` указатели к константным могут ```cpp int f() { try { ... throw 10; ... throw "abc"; ... throw A(); ... } catch (int a) { ... throw ...; // тогда обработается функцией выше ... } catch (const char* s) { ... } catch (A &x) { ... } catch (...) { // все остальные исключения } } ``` В случае возвращение класса, который наследуется от базового, "ловить" надо сначала производный, после - базовый Деструктор для создаваемого класса вызывается только после фулл обработки исключения (если catch сам вызвал throw) ```cpp int f() throw(int, char) { try { ... throw 1.2; ... } catch (double) { ... } } ``` `unexpected()` - вызывается, если мы на внешнюю функцию передаём исключение типа, который не указан ```cpp // никакие не передавать вовне int f() throw(); after c++17 only: int f() noexcept; ``` ### Алгоритм обработки исключений - создание временного объекта типа возвращаемого исключения - уничтожение объектов в `try` блоке - выход из `try` - подбор нужного обработчика - если больше исключений нет - деструктор временного объекта - если не обработано - выход к внешнему обработчику ```cpp 5.14. Что напечатает следующая программа? struct S { S ( int a) { try { if (a > 0) throw *this ; else if (a < 0) throw 0; } catch ( S & ) { cout << “SCatch_S&” << endl; } catch (int ) { throw ; } cout << “SConstr” << endl; } S (const S & a) { cout << “Copy” << endl; } ~S ( ) { cout << “Destr” << endl; } }; int main ( ) { try { S s1( 0 ), s2 ( 5 ); cout << “Main” << endl; } catch (S &) { cout << “MainCatch_S&” << endl; } catch ( ... ) { cout << “MainCatch_...” << endl; } return 0; } ``` Результат отработки программы: ```text Sconstr Copy Scatch_s& Destr Sconstr Main Destr Destr ``` 1 14 15 CatchB bad_cast 63 63 3 ... End