This repository has been archived on 2026-07-28. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
2025-04-13 21:48:15 +03:00

4.0 KiB

Семинар 6

RTTI - Run Time Type Identification

  • typeid
  • dynamic_cast

typeid

typeid возвращает тип объекта/указателя. Если указатель на класс с виртуальными функциями, вернёт именно тип объекта. Иначе - указателя.

Для type_info переопределённые операции и методы:

  • ==
  • !-
  • .name
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

class A {
public:
    virtual void f() {}
};

class B : public A {};

int main () {
    A *pa, a; 
    B *pb, b;
    pa = &b;
    // безопасно приводит, вернёт не NULL в случае успеха
    pb = dynamic_cast<B*>(pa);
}
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<B&>(pa); // выкинет bad_cast
}

Исключения

try - throw - catch

terminate() - в случае, если ничего не обработалось

приводится в catch указатели к константным могут

int f() {
    try {
        ...
        throw 10;
        ...
        throw "abc";
        ...
        throw A();
        ...
    } catch (int a) {
        ...
        throw ...; // тогда обработается функцией выше
        ...
    } catch (const char* s) {
        ...
    } catch (A &x) {
        ...
    } catch (...) { // все остальные исключения

    }
}

В случае возвращение класса, который наследуется от базового, "ловить" надо сначала производный, после - базовый Деструктор для создаваемого класса вызывается только после фулл обработки исключения (если catch сам вызвал throw)

int f() throw(int, char) {
    try {
        ...
        throw 1.2;
        ...
    } catch (double) {
        ...
    }
}

unexpected() - вызывается, если мы на внешнюю функцию передаём исключение типа, который не указан

// никакие не передавать вовне
int f() throw();

after c++17 only:
int f() noexcept;

Алгоритм обработки исключений

  • создание временного объекта типа возвращаемого исключения
  • уничтожение объектов в try блоке
  • выход из try
  • подбор нужного обработчика
  • если больше исключений нет - деструктор временного объекта
  • если не обработано - выход к внешнему обработчику
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;
}

Результат отработки программы:

Sconstr
Copy
Scatch_s&
Destr
Sconstr
Main
Destr
Destr

1 14 15 CatchB bad_cast 63 63 3 ... End