Объектно-ориентированное программирование на C++, страница 7
Описание файла
PDF-файл из архива "Объектно-ориентированное программирование на C++", который расположен в категории "". Всё это находится в предмете "информатика" из 1 семестр, которые можно найти в файловом архиве МГТУ им. Н.Э.Баумана. Не смотря на прямую связь этого архива с МГТУ им. Н.Э.Баумана, его также можно найти и в других разделах. Архив можно найти в разделе "книги и методические указания", в предмете "информатика" в общих файлах.
Просмотр PDF-файла онлайн
Текст 7 страницы из PDF
*/}catch ( тип_исключения1 переменная ) {/* ... */}catch ( тип_исключения2 переменная ) {/* ... */}Catch-блок, который может перехватить любое исключение,записывается какcatch (...) {/* ... */}85 / 99Пример: перехват исключения std::bad_allocБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийИсключенияПорождениеПерехват иобработкаСпецификацияКласс exception12# include < iostream >using namespace std ;345678910111213141516int main (){try {size_t n ;cin >> n ;int * a = new int [ n ];cout << " success \ n " ;delete [] a ;} catch ( bad_alloc ) {cout << " out ␣ of ␣ memory \ n " ;}return 0;}Исключение std::bad_alloc порождается операцией newпри невозможности выделить блок динамической памяти.86 / 99Жизненный цикл объектов-исключенийБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийИсключенияПорождениеПерехват иобработкаСпецификацияКласс exceptionИсследуем жизненный цикл объектов исключений с помощью класса A, который протоколирует факты создания, копирования и уничтожения своих экземпляров:struct A {bool is_copy ;A ();A ( const A & obj );~ A ();void report ();};A :: A (): is_copy ( false ){ cout << " new " << ’\ n ’; }A :: A ( const A & obj ): is_copy ( true ){ cout << " copy " << ’\ n ’; }A ::~ A () { cout << " destroy ␣ " << is_copy << ’\ n ’; }void A :: report () { cout << " report \ n " ; }87 / 99Пример 1: жизненный циклобъектов-исключенийБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийИсключенияПорождениеПерехват иобработкаСпецификацияКласс exceptionПорождение объекта-исключения в куче и перехват, прикотором он передаётся в catch-блок по указателю.
В концеcatch-блока необходимо явное уничтожение объекта.int main (){try {throw new A ();} catch ( A * a ) {a - > report ();delete a ;}return 0;}Вывод:newreportdestroy 088 / 99Пример 2: жизненный циклобъектов-исключенийБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийИсключенияПорождениеПерехват иобработкаСпецификацияКласс exceptionПорождение временного объекта-исключения и перехват,при котором создаётся его копия.int main (){try {throw A ();} catch ( A a ) {a .
report ();}return 0;}Вывод:newcopyreportdestroy 1destroy 089 / 99Пример 3: жизненный циклобъектов-исключенийБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийИсключенияПорождениеПерехват иобработкаСпецификацияКласс exceptionПорождение временного объекта-исключения и перехват,при котором он передаётся в catch-блок по ссылке, т.е. безсоздания копии.int main (){try {throw A ();} catch ( A & a ) {a . report ();}return 0;}Вывод:newreportdestroy 090 / 99Пример: уничтожение автоматических объектовв процессе передачи исключения в catch-блокБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийИсключенияПорождениеПерехват иобработкаСпецификацияКласс exception1# include < iostream >23struct Dummy { ~ Dummy (); };45Dummy ::~ Dummy () { std :: cout << " # ␣ " ; }6789101112void recur ( int n ) {if ( n == 0) throw " base ␣ of ␣ recursion " ;Dummy d ;recur (n -1);std :: cout << " should ␣ never ␣ be ␣ reached ! " ;}131415161718int main (){try { recur (10); } catch (...) { }return 0;}Вывод:# # # # # # # # # #91 / 99Перехват исключений в инициализаторахконструкторовБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийИсключенияПорождениеПерехват иобработкаСпецификацияКласс exceptionНапомним, что конструкторы в C++ могут иметь спискиинициализаторов, в которых вызываются конструкторыобъектов, расположенных в полях, и конструкторы базовыхклассов.Так как конструкторы полей и базовых классов могут порождать исключения, нужно уметь эти исключения перехватывать, например, для протоколирования неудачногосоздания объектов в логах.
Для этой цели служат специальные try-блоки, обрамляющие тело конструктора, которыесинтаксически выглядят какКласс :: Класс ( параметры_констр ук то ра ) try: список_инициализац ии{ тело_конструктора }catch ( исключение ) { тело_обработ чи ка _и с кл юч ен ия }...Отметим, что если catch-блок не оканчивается порождениемдругого исключения, старое исключение не уничтожается и92 / 99передаётся дальше.Пример: перехват исключений винициализаторах конструкторовБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийИсключенияПорождениеПерехват иобработкаСпецификацияКласс exception12# include < iostream >using namespace std ;345struct A { A ( int x ); };struct B : public A { B ( int x ); };67A :: A ( int x ) { if ( x < 0) throw " negative " ; }8910B :: B ( int x ) try : A ( x ) { }catch ( const char * s ) { cout << " 1 ␣ " ; }11121314151617181920int main (){try {B b ( -10);} catch (...) {cout << " 2\ n " ;}return 0;}1 293 / 99Спецификатор throw в заголовках функцийБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийИсключенияПорождениеПерехват иобработкаСпецификацияКласс exceptionКак и в языке Java, в C++ можно перечислить типы исключений, которые может порождать вызов функции.
Дляэтого после списка формальных параметров следует разместить спецификатор throw:throw ( список типов исключений )Семантика этого спецификатора несколько отличается отсемантики соответствующей конструкции языка Java, аименно:вызов функции, для которой разрешённые исключенияне указаны, может порождать любые исключения;! вызов функции со спецификатором throw() не порождает никаких исключений;! компилятор не следит за тем, какие исключения порождаются внутри функции: вместо этого неразрешённыеисключения просто не могут выйти за пределы функциии приводят к аварийному завершению программы.!94 / 99Пример 1: спецификатор throwБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийИсключенияПорождениеПерехват иобработкаСпецификацияКласс exception12# include < iostream >using namespace std ;34567void f () throw ( int ){throw 2;}891011121314151617int main (){try {f ();} catch ( int e ) {cout << " int : ␣ " << e << ’\ n ’;}return 0;}Вывод (исключение 2 «пропущено» наружу из функции f):int : 295 / 99Пример 2: спецификатор throwБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийИсключенияПорождениеПерехват иобработкаСпецификацияКласс exception12# include < iostream >using namespace std ;34567void f () throw (){throw 2;}891011121314151617int main (){try {f ();} catch ( int e ) {cout << " int : ␣ " << e << ’\ n ’;}return 0;}Вывод (исключение 2 «не выпущено» из функции f):terminate called after throwing an instanceof ’ int ’96 / 99Спецификатор throw и переопределениевиртуальных методовБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийИсключенияПорождениеПерехват иобработкаСпецификацияКласс exceptionПо очевидным соображениям, связанным с поддержкойполиморфизма, переопределение виртуальных методов недолжно ослаблять ограничения, накладываемые спецификатором throw, т.е.
переопределённому методу не разрешаетсяпорождать исключения, не порождаемые методом базовогокласса.struct A {virtual void f () throw ( int ) {}};struct B : public A {void f () throw ( float ) {}};Сообщение об ошибке:error : looser throw specifier for’ virtual ␣ void ␣ B :: f () ␣ throw ␣ ( float ) ’overriding ’ virtual ␣ void ␣ A :: f () ␣ throw ␣ ( int ) ’97 / 99Создание классов исключенийБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийИсключенияПорождениеПерехват иобработкаСпецификацияКласс exceptionРекомендуемым способом создания классов исключений вязыке C++ является наследование их от библиотечногокласса exception (его объявление расположено в заголовочном файле <exception>):class exception {public :exception () throw ();exception ( const exception &) throw ();exception & operator = ( const exception &) throw ();virtual ~ exception () throw ();virtual const char * what () const throw ();};В производном от exception классе нужно переопределитьвиртуальный метод what, возвращающий ASCIIZ-строку сописанием исключительной ситуации.98 / 99Пример: создание классов исключенийБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийИсключенияПорождениеПерехват иобработкаСпецификацияКласс exception12# include < exception >using namespace std ;345678struct MyException : public exception{const char * what () const throw (){ return " This ␣ is ␣ my ␣ exception " ; }};91011121314int main (){throw MyException ();return 0;}Вывод:terminate called after throwing an instanceof ’ MyException ’what (): This is my exceptionAborted99 / 99.