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

13.2.1 Синтаксис основних конструкцій

Управління виключеннями С++ є частиною стандарта ANSI C++. Цей стандарт підтримує кінцеву модель управління: після того, як управління було зафіксоване, процедура обробки не може вимагати, щоб виконання було продовжене з точки виключення. Виключення С++ також не підтримують обслуговування асинхронних подій, таких, як помилки обладнання чи обробку переривань. Обслуговуються лише виключення, які в явному вигляді сигналізуються деякою функцією. В контексті управління виключеннями в С++ використовуються три ключових слова: try, catch та thow.

13.2.1.1 Використання try та сatch

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

try

{

cout<<“in try-block . . .”<<endl;

func(); //функція може генерувати виключення

}

Ключове слово catch слідує за try-блоком і позначає секцію кода, в яку може бути передано управління в тому випадку, коли відбудеться виключення (називають catch-обробник чи обробник виключення). За ключовим словом слідує опис виключення, поміщений у фігурних дужках, який складається з імені типу та необов’язкової змінної. Ім’я типу ідентифікує тип виключення, яке даний код може обслуговувати. Можна розглянути опис виключення як параметр функції . За try-блоком може слідувати кілька операторів catch. Розглянемо приклад:

#include<iostream.h>

void func(void);

int main(void)

{

try

{ cout “in try=block . . .”<<endl;

func();//може генерувати виключення

}

catch(int i)

{ }

catch( const char*)

{ }

//обробляє всі необслужені виключення

catch(...)

{ }

return 0;

}

Оператор catch з трьома крапками (. . .) перехоплює виключення будь-якого типу і повинен бути останням з операторів catch, що слідують за try-блоком.

13.2.1.2 Використання throw

Ключове слово throw викидає виключення і викликає перехід управління до обробника. За ключовим словом може слідувати вираз.

throw з операндом

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

Приклад:

#include<cstring.h>

void func1()

{ if (що небудь не впорядку) throw ” виявлена помилка”; }

void func2()

{

if(що_небудь_не_в_порядку)

{ string str(“Oй !!!!!!!”);

throw str;

}

}

Відмітимо, що викидатись можуть як стандартні типи, так і типи користувача. Тоді можна передати обробнику об’єкт, навантажений інформацією.

throw без операнда

Якщо ключове слово throw використовується без операнда, то знову викидається те виключення, яке обробляється в даний момент. Звідси випливає, що така форма оператора може використовуватись тільки в cach-обробнику

( чи в функції, яка явно чи неявно ним викликається).

Перехоплення throw

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

  • створюють копію викинутого об’єкта-змінної;

  • Розмотують стек, викликаючи деструктори локальних об’єктів, які виходять з області видимості;

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

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

#include<fstream.h>

class TaleTelling

{public:

TaleTelling()

{ cout<<“Жили-були TaleTelling”<<endl;}

~TaleTelling()

{cout<<“І померли TaleTelling...”<<endl;

}};

void function1(void)

{

ifsteram ifs(“\\invalid\\file\\name”);

if (!ifs)

{cout<<“викидаємо виключення”<<endl;

throw “помилка при відкриттю файла”;

}}

void function2(void)

{

//створимо локальний об’єкт, щоб перевірити виклик деструктора при //розмотуванні стека

TaleTelling tellme;

//викликається функція, що викидає виключення

functoin1();}

int main(void)

{

try

{

cout<<“увійшли в try-блок”<<endl;

function2();

cout<<“виходимо з try-блока”<<endl;

}

catch(int i)

{

cout<<“викликаний обробник int”<<endl;

return -1;

}

catch(const char *p)

{

cout<<“викликаний обробник char*”<<endl;;

return -1;

}

catch(...)

{cout<<“викликаний обробник catch_all”<<endl;

return -1;

}

return 0; // обійшлося без пригод

}

Результати роботи:

увійшли в try-блок

Жили-були TaleTelling

викидаємо виключення

І померли TaleTelling...

викликаний обробник char*[ помилка при відкритті файла]

Відмітимо наступні моменти:

деструктор локальної змінної tellme був викликаний вірно, хоч і з функції function1 управління було передане безпосередньо обробнику виключення;

оператор з main() , який містить повідомлення “виходимо з try-блока “ так і не був виконаним.