Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП.doc
Скачиваний:
77
Добавлен:
07.03.2016
Размер:
1.78 Mб
Скачать

6.2 Синтаксис виключень

Ключове слово try слугує для позначення контрольованого блоку – код, в якому може генеруватися виключення. Блок береться у фігурні дужки:

try

{

}

Всі функції, які прямо або побічно викликаються з try-блока, також вважаються такими, що належать цьому блоку.

Генерація (породження) виключення відбувається по ключовому слову throw, яке вживається або з параметром, або без нього:

throw [ вираз ];

Тип виразу, що стоїть після throw, визначає тип породжуваного виключення. При генерації виключення виконання поточного блоку припиняється, і відбувається пошук відповідного обробника і передача йому управління. Як правило, виключення генерується не безпосередньо в try-блоці, а у функціях, прямо або побічно в нього вкладених. Не завжди виключення, що виникло у внутрішньому блоці, може бути відразу правильно оброблено. В цьому випадку використовуються вкладені контрольовані блоки, і виключення передається на вищий рівень за допомогою ключового слова throw без параметрів.

Обробники виключень починаються з ключового слова catch, за яким в дужках слідує тип оброблюваного виключення. Вони повинні розташовуватися безпосередньо за try-блоком. Можна записати один або декілька обробників відповідно до типів оброблюваних виключень. Синтаксис обробників нагадує визначення функції з одним параметром – типом виключення.

Існує три форми запису:

catch(тип ім’я) { ... /* тіло обробника */ }

catch(тип){ ... /* тіло обробника */ }

catch(...){ … /* тіло обробника */ }

Перша форма застосовується, коли ім'я параметра використовується в тілі обробника для виконання яких-небудь дій – наприклад, виведення інформації про виключення. Друга форма не припускає використання інформації про виключення, грає роль тільки його тип. Багатокрапка замість параметра означає, що обробник перехоплює всі виключення. Оскільки обробники є видимими в тому порядку, в якому вони записані, обробник третього типу слід поміщати після всіх останніх. Приклад:

catch(int i)

{

... // Обробка виключень типу int

}

catch(const char *)

{

... // Обробка виключень типу const char*

}

catch(Overflow)

{

... // Обробка виключень класу Overflow

}

catch(...)

{

... // Обробка всіх необслужених виключень

}

Після обробки виключення управління передається першому операторові, що знаходиться безпосередньо за обробниками виключень. Туди ж, минувши код всіх обробників, передається управління, якщо виключення в try-блоці не згенерувало.

6.3 Перехоплення виключень

Коли за допомогою throw генерується виключення, функції виконавчої бібліотеки C++ виконують наступні дії:

1) створюють копію параметра throw у вигляді статичного об'єкту, який існує до тих пір, поки виключення не буде оброблено;

2) у пошуках відповідного обробника розкручують стек, викликаючи деструктори локальних об'єктів, що виходять з області дії;

3) передають об'єкт і управління обробникові, що має параметр, сумісний з типом цього об'єкту.

При розкручуванні стека всі обробники на кожному рівні є видимими послідовно, від внутрішнього блоку до зовнішнього, поки не буде знайдений відповідний обробник.

Обробник вважається знайденим, якщо тип об'єкту, вказаного після throw:

  • той же, що і вказаний в параметрі catch (параметр може бути записаний у формі Т, const Т, Т& або const Т&, де Т – тип виключення);

  • є похідним від вказаного в параметрі catch (якщо спадкування проводилося з ключем доступу public);

  • є вказівкою, яка може бути перетворена по стандартних правилах перетворення вказівок до типу вказівки в параметрі catch.

Обробники похідних класів слід розміщувати до обробників базових, оскільки інакше їм ніколи не буде передано управління. Обробник вказівки типу void автоматично приховує вказівку будь-якого іншого типу, тому його також слід розміщувати після обробників вказівок конкретного типу.

Розглянемо приклад.

#include <fstream>

using namespace std;

class Hello

{

// Клас, який інформує про своє створення та знищення

public:

Hello(){cout << "Hello!" << endl;}

~Hello(){cout << "Bye!" << endl;}

};