Скачать презентацию Исключения Степанюк Константин Сергеевич 24 const gmail com Скачать презентацию Исключения Степанюк Константин Сергеевич 24 const gmail com

#7 Исключения.pptx

  • Количество слайдов: 24

Исключения Степанюк Константин Сергеевич 24 const@gmail. com Исключения Степанюк Константин Сергеевич 24 const@gmail. com

Задание • Описать класс Person, имеющий поля first. Name и last. Name • Описать Задание • Описать класс Person, имеющий поля first. Name и last. Name • Описать производный класс Student расширяющий класс Person, имеющий поле group. Num • Для каждого поля описать (прототипы) функции селекторы и модификаторы • Описать и реализовать виртуальную функцию print(), которая выводит список всех полей класса на экран

class Devided. By. Zero. Exception { public: Devided. By. Zero. Exception() : message( class Devided. By. Zero. Exception { public: Devided. By. Zero. Exception() : message("Деление на нуль") {} void print. Message() const {cout <>number 1 >>number 2; try { float result = division(number 1, number 2); cout <<"частное равно: " <

Перехват исключений • Исключения, находящиеся внизу иерархии наследования должны перехватываться первыми voidf() { try Перехват исключений • Исключения, находящиеся внизу иерархии наследования должны перехватываться первыми voidf() { try { //… } catch (overflow_error) { //… } catch (runtime_error) { //… } catch (bad_alloc){ //… } catch (exception){ //… } catch (…) { … } }

Исключения стандартной библиотеки Исключения стандартной библиотеки

Обработка исключений для перехвата исключения с возможностью работы с ним, необходимо в блоке catch Обработка исключений для перехвата исключения с возможностью работы с ним, необходимо в блоке catch использовать переменную –формальный параметр: try { … } catch (exception &ex) { cout<

Исключения и параметры функций • Синтаксис определения блоков catch во многом похож на синтаксис Исключения и параметры функций • Синтаксис определения блоков catch во многом похож на синтаксис объявления функций: class Widget {…}; class My. Ex: public excetpion {…}; void f(Widget w); void g(Widget &w); void h(const Widget &w); void bar(Widget *pw); void foo(const Widget *pw); catch(My. Ex ex); catch(My. Ex &ex); catch(const My. Ex &ex); catch(My. Ex *pe); catch(const My. Ex *pe); • Главное отличие: при генерации исключения всегда происходит копирование выбрасываемого объекта, а в случае вызова функции по ссылке –копирования не происходит

Исключения и функции -пример: class Parent {…}; class Child: public Parent{…}; void f (Parent Исключения и функции -пример: class Parent {…}; class Child: public Parent{…}; void f (Parent &w); … void g () { Child ch; Parent &rp = ch; //rp ссылаетсяна объект класса Child f(rp); //В функцию f передан объект класса Child try { //вызывается конструктор. Parent(const Parent&) throw rp; //выброшен объект класса Parent!!! } catch (Parent &pe) { //перехвачен объект класса Parent } }

Перехват исключений по значению и через указатель • перехват по значению –лишнее копирование: try Перехват исключений по значению и через указатель • перехват по значению –лишнее копирование: try { throw My. Ex(); //копирование при выбросе } catch (My. Ex ex) {} //копирование при перехвате • перехват через указатель –кто освободит память? f () { throw new My. Ex(); } g () { try { f(); } catch (My. Ex *pe) { //нужно не забыть освободить память delete pe; //а в друг объект не был создан в свободной //памяти? } }

Лучшая стратегия –перехват по ссылке • При перехвате по ссылке не происходит лишнего копирования Лучшая стратегия –перехват по ссылке • При перехвате по ссылке не происходит лишнего копирования объекта исключения и при этом сохраняются преимущества полиморфизма: class Base. Exception {…}; class Child. Exception : public Base. Exception{…}; f() { //… throw Child. Exception(); } g() { try { } catch (Base. Exception&ex) { //перехвачен объект класса Child. Exception } }

Исключения и функции –итог • В отличие от функций при возбуждении исключения всегда происходит Исключения и функции –итог • В отличие от функций при возбуждении исключения всегда происходит копирование выбрасываемого объекта • В отличие от функций, где для приведения типов аргументов разрешены преобразования определяемые пользователем, при перехвате исключений рассматриваются только преобразования вверх по иерархии наследования (upcast) • Блоки catch срабатывают в порядке их перечисления (указания), а не по принципам наилучшего соответствия типа аргумента, как это имеет место быть при разрешении перегруженных функций

Проблема управления ресурсами void use. File(const char* fname) { FILE *fp = fopen(fname, “w”); Проблема управления ресурсами void use. File(const char* fname) { FILE *fp = fopen(fname, “w”); … // вдруг произойдет исключение? fclose(fp); } void use. File 2(const char* fname) { FILE *fp = fopen(fname, ”w”); try { //… } catch (…) { fclose(fp); //некрасиво –две точки закрытия throw; } fclose(fp); // легко можно запутаться }

Для ресурсов можно использовать классы –обертки class File. Ptr { FILE *fp; public: File. Для ресурсов можно использовать классы –обертки class File. Ptr { FILE *fp; public: File. Ptr(const char* path, const char* mode); File. Ptr(FILE *fp) { this->fp = fp; } ~File. Ptr() { fclose (fp); } operator FILE*() {return fp; } }; void use. File 3 (const char *fname) { File. Ptr fp(fname, ”w”); //… Даже если возникнет исключение объект будет удален, // вызовется деструктор ~File. Ptr в котором закроется файл } • Удаление объектов происходит в процессе обратной раскрутки стека при обработки исключений (“stack unwinding”)

Исключения при создании объектов • Объект не считается созданным пока не завершилось создание всех Исключения при создании объектов • Объект не считается созданным пока не завершилось создание всех его частей и не завершил свою работу конструктор • В случае возникновения исключительной ситуации во время создания объекта, все уже созданные части корректно уничтожаются в процессе обратной раскрутки стека • Следует избегать выброса исключений из деструктора, так как в случае если деструктор выполняется в процессе обратной раскрутки стека при обработки исключения и выброшено новое исключение, то вызывается функция std: : terminate

Функция terminate() • Вызывается при разрушении стека: – если выбрасывается исключение во время обратной Функция terminate() • Вызывается при разрушении стека: – если выбрасывается исключение во время обратной раскрутки стека при уже выброшенном исключении – если вызывается throw; вне блока перехвата исключения (повторная генерация если выброса исключения не было) – если произошло исключение но не было перехвачено – если конструктор глобального статического объекта завершается аварийно с выбросом исключения • По умолчанию terminate() вызывает abort() • set_terminate позволяет установить обработчик terminate • bool uncaught_exception() проверяет было ли исключение перехвачено (можно ли вызвать throw)

Декларация списка исключений void f() throw (Exception 1, Exception 2) {} • Используется для Декларация списка исключений void f() throw (Exception 1, Exception 2) {} • Используется для спецификации списка допустимых к генерации исключений в функции • Если функция попытается выбросить исключение не являющееся объектом типа Exception 1 или Exception 2 или их наследников, то произойдет вызов функции ловушки std: : unexpected(), которая по умолчанию вызывает std: : terminate(), но может быть переопределена программистом (set_unexpected) • Проверка осуществляется на этапе исполнения а не компиляции, проверка на этапе компиляции отдана на усмотрение разработчикам сред void f() { // Может выбрасывать любые исключения } void f() throw () { //Не может выбрасывать исключения }

Исключение bad_exception • Менее радикальный механизм чем вызов terminate в обработчике unexpected • Будучи Исключение bad_exception • Менее радикальный механизм чем вызов terminate в обработчике unexpected • Будучи добавленным в список специфицируемых функцией исключений обеспечивает выброс исключения bad_exception вместо вызова функции-ловушки unexpected class X {}; class Y {}; void f() throw (X, std: : bad_exception) { //… throw Y(); //Выбросится std: : bad_exception вместо вызова //unexpected }

Исключения и конструкторы class Image { public: Image(const string& file. Name)}; class Audio. Clip Исключения и конструкторы class Image { public: Image(const string& file. Name)}; class Audio. Clip { public: Audio. Clip(const string& file. Name) }; class Entry { string the. Name; Image *p. Image; Audio. Clip *p. Clip; public: Entry(const string& name, const string& image. Location, const string& audio. Location) : the. Name(name), p. Image(0), p. Clip(0) { p. Image = new Image(image. Location); p. Clip = new Audio. Clip(audio. Location); } ~Entry() { delete p. Image; delete p. Clip; } };

Обработка исключений в конструкторе Entry: : Entry(const string& name, const string& image. Location, const Обработка исключений в конструкторе Entry: : Entry(const string& name, const string& image. Location, const string& audio. Location) : the. Name(name), p. Image(0), p. Clip(0) { try { p. Image = new Image(image. Location); p. Clip = new Audio. Clip(audio. Location); } catch (…) { delete p. Image; delete p. Cilp; throw; } }

Обработка исключений в блоке инициализации Entry: : Entry(const string& name, const string& image. Location, Обработка исключений в блоке инициализации Entry: : Entry(const string& name, const string& image. Location, const string& audio. Location) try : the. Name(name), p. Image(new Image(image. Location)), p. Clip(new Audio. Clip(audio. Location)) { //Тело конструктора, также находящееся //в области действия //try -catch } catch (…) { delete p. Image; delete p. Clip; //… }

Использование auto_ptr class Entry { string the. Name; auto_ptr<Image> p. Image; auto_ptr<Audio. Clip> p. Использование auto_ptr class Entry { string the. Name; auto_ptr p. Image; auto_ptr p. Clip; public: Entry(const string& name, const string& image. Location, const string& audio. Location) : the. Name(name), p. Image(new Image(image. Location)), p. Clip(new Audio. Clip(audio. Location)) {} // Теперь пустое тело конструктора ~Entry() {} };

placement delete void* operator new (size_t, void*) throw(); void* operator new[] (size_t, void*) throw(); placement delete void* operator new (size_t, void*) throw(); void* operator new[] (size_t, void*) throw(); void operator delete(void *p, void*) throw(); void operator delete[](void *p, void*) throw(); • placement delete вызывается если произошло исключение при вызове соответствующего placement new

Проверка на внимательность class Parent. Exception {}; class Child. Exception : public Parent. Exception Проверка на внимательность class Parent. Exception {}; class Child. Exception : public Parent. Exception {}; int main() { try { throw Child. Exception(); } catch(Parent. Exception) { cout <<"Parent. Exception" <

Упражнение • Создать класс Rectangle(прямоугольник). Класс имеет атрибуты length(длина) и width(ширина). Требуется реализовать: – Упражнение • Создать класс Rectangle(прямоугольник). Класс имеет атрибуты length(длина) и width(ширина). Требуется реализовать: – 1. Селекторы – 2. Модификаторы, генерирующие исключения Bad. Length. Exception и Bad. Width. Exception если атрибут <= 0 – 3. Функцию main() {…} с блоком try/catch, которая пытается создать прямоугольник с неверными атрибутами и выводит сообщение о соответствующей ошибке в блоке catch.