Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
02 семестр / Лекции и семинары / Лекции по С++ / Лекции / Язык программирования C++_7.ppt
Источник:
Скачиваний:
75
Добавлен:
04.03.2014
Размер:
308.74 Кб
Скачать

Глава 7.

Исключения

МГТУ им. Н.Э. Баумана Факультет Информатика и системы управления

Кафедра Компьютерные системы и сети Лектор: д.т.н., проф.

Иванова Галина Сергеевна

1

7.1 Механизм исключений С++

В С и С++ используются разные стандарты обработки исключений.

Генерация исключений:

throw [<Тип>](<Аргументы>);

где <тип> – тип (чаще класс) генерируемого значения; если тип не указан, то компилятор определяет его исходя из типа аргумента (обычно это один из встроенных типов);

<аргументы> – одно или несколько выражений, значения которых будут использованы для инициализации генерируемого объекта.

Примеры:

throw (”Неверный параметр”); /* тип const char * с указанным в кавычках значением */

throw (221); /* тип const int с указанным значением */

class E { //класс исключения

 

public: int num;

// номер исключения

E(int n): num(n){}

// конструктор класса

}

 

2

throw E(5); // класс E

Перехват и обработка исключений

try {<Защищенный код>}

catch (<Ссылка на тип>){<Обработка исключений>} При этом:

1)исключение типа T будет перехватываться обработчиками типов T, const T, T& или const T&;

2)обработчики типа базового класса перехватывают исключения типа производных классов;

3)обработчики типа void* перехватывают все исключения типа указателя.

Блок catch, для которого в качестве типа указано «…» обрабатывает исключения всех типов.

Примеры:

try {<Операторы>} // выполняемый фрагмент программы catch (EConvert& A){<Операторы>} /* перехват исключений

типа EConvert */

catch (char* Mes){<Операторы>} //перехват исключений char*

< > 3

catch(…) { Операторы } //перехват остальных исключений

Возобновление исключения

Если перехваченное исключение не может быть обработано, то оно возобновляется.

Пример:

class

E{};

// класс исключения

void somefunc()

 

{

if(<условие> throw Out(); }// генерация исключения

void func()

{try { somefunc(true); }

catch(E& e){ if (<условие>) throw; } /* если здесь исключение обработать нельзя, то возобновляем его */ }

void mainfunc()

{try { func();}

catch(E& e){ … } } // здесь обрабатываем исключение

4

Доступ к аргументам исключения

Использование имени переменной в качестве параметра оператора catch позволяет операторам обработки получить доступ к аргументам исключения через указанное имя.

Пример:

 

 

class E //класс исключения

 

{ public: int num;

// номер исключения

E(int n): num(n){}

// конструктор

}

 

 

 

 

try { ...

 

 

throw E(5);

// генерируемое исключение

...}

catch (E& e){if (e.num==5) {…}} // получен доступ к полю

5

Последовательность обработки исключения

при генерации исключения происходит конструирование временного объекта исключения;

выполняется поиск обработчика исключения;

при нахождении обработчика создается копия объекта с указанным именем;

уничтожается временный объект исключения;

выполняется обработка исключения;

уничтожается копия исключения с указанным именем.

Поскольку обработчику передается копия объекта исключения, желательно в классе исключения с динамическими полями предусмотреть копирующий конструктор и деструктор.

6

Обработка объекта исключения (Ex7_1)

#include "stdafx.h" #include <stdio.h> class MyException

{protected: int nError;

public: MyException(int nErr) {nError=nErr;}

~MyException(){puts("destructor");}

void ErrorPut(){printf("Error %d.\n",nError);}

};

int main(int argc, char* argv[])

{

try

{

throw MyException(5);

}

catch(MyException E){E.ErrorPut();} puts("program");

return 0;

}

destructor

Error 5. destructor destructor program

Press any key to continue

7

Спецификация исключений

При объявлении функции можно указать, какие исключения она может генерировать:

throw(<тип>,<тип>…). Пример:

void func() throw(char*,int){…} /*функция может генерировать исключения char* и int */

Спецификация исключений не считается частью типа функции и, следовательно, ее можно изменить при переопределении:

class ALPHA

{public: struct ALPHA_ERR{};

virtual void vfunc() throw(ALPHA_ERR){}

};

class BETA : public ALPHA { public:

 

void vfunc() throw(char *) {}

8

};

 

 

 

Уничтожение локальных переменных при обработке исключения (Ex7_2)

#include "stdafx.h"

При «раскручивании» стека

#include <iostream.h>

локальные переменные

void MyFunc( void );

уничтожаются

 

class CTest

 

{public: CTest(){};

 

~CTest(){};

const char *ShowReason() const

{ return "Exception in CTest class."; }

};

class CDtorDemo {public: CDtorDemo();

~CDtorDemo();

};

CDtorDemo::CDtorDemo()

{cout << "Constructing CDtorDemo." << endl;}

CDtorDemo::~CDtorDemo()

9

{ cout << "Destructing CDtorDemo." << endl;}

Уничтожение локальных переменных при обработке исключения (2)

void MyFunc() {CDtorDemo D;

cout<<"In MyFunc().Throwing CTest exception."<<endl; throw CTest();

}

int main()

{cout << "In main." << endl; try

{cout<<"In try block, calling MyFunc()."<<endl; MyFunc(); }

catch(CTest E)

{cout << "In catch handler." << endl; cout << "Caught CTest exception type: ";

cout << E.ShowReason() << endl;

}

catch( char *str )

{cout<<"Caught other exceptions: "<<str<<endl;} cout<<"Back in main. Execution resumes here."<<endl;

return 0;}

10