Чтение онлайн

на главную - закладки

Жанры

Шрифт:

7.3.4 Обработка ошибок

Есть четыре подхода к проблеме, что же делать, когда во время выполнения универсальное средство вроде slist сталкивется с ошибкой (в С++ нет никаких специальных средств языка для обработки ошибок):

1. Возвращать недопустимое значение и позволить пользвателю его проверять

2. Возвращать дополнительное значение состояния и рарешить пользователю проверять его

3. Вызывать функцию ошибок, заданную как часть класса slist или

4. Вызывать функцию ошибок, которую предположительно предоставляет пользователь.

Для небольшой программы, написанной ее единственным пользователем, нет фактически никаких особенных причин препочесть одно из этих решений другим. Для средства общего наначения ситуация совершенно иная.

Первый подход, возвращать недопустимое значение, неосществим. Нет совершенно никакого способа узнать, что некоторое конкретное значение будет недопустимым во всех прменениях slist.

Второй подход, возвращать значение состояния, можно ипользовать в некоторых классах (один из вариантов этого плана применяется в стандартных потоках ввода/вывода istream и ostream; как – объясняется в #8.4.2). Здесь, однако, имеется серьезная проблема, вдруг пользователь не позаботится проврить значение состояния, если средство не слишком часто поводит. Кроме того, средство может использоваться в сотнях или даже тысячах мест программы. Проверка значения в каждом месте сильно затруднит чтение программы.

Третьему подходу, предоставлять функцию ошибок, недостет гибкости. Тот, кто реализует универсальное средство, не может узнать, как пользователи захотят, чтобы обрабатывались ошибки. Например, пользователь может предпочитать сообщения на датском или венгерском.

Четвертый подход, позволить пользователю задавать фунцию ошибок, имеет некоторую привлекательность при условии, что разработчик предоставляет класс в виде библиотеки (#4.5), в которой содержатся стандартные функции обработки ошибок.

Решения 3 и 4 можно сделать более гибкими (и по сути эвивалентными), задав указатель на функцию, а не саму функцию. Это позволит разработчику такого средства, как slist, предотавить функцию ошибок, действующую по умолчанию, и при этом программистам, которые будут использовать списки, будет легко задать свои собственные функции ошибок, когда нужно, и там, где нужно. Например:

typedef void (*PFC)(char*); // указатель на тип функция extern PFC slist_handler; extern PFC set_slist_handler(PFC);

Функция set_slist_hanlder позволяет пользователю замнить стандартную функцию. Общепринятая реализация предосталяет действующую по умолчанию функцию обработки ошибок, котрая сначала пишет сообщение об ошибке в cerr, после чего завершает программу с помощью exit:

#include «slist.h» #include «stream.h»

void default_error(char* s)

(* cerr «„ s «« «\n“; exit(1); *)

Она описывает также указатель на функцию ошибок и, для удобства записи, функцию для ее установки:

PFC slist_handler = default_error;

PFC set_slist_handler(PFC handler); (* PFC rr = slist_handler; slist_handler = handler; return rr; *)

Обратите внимание, как set_slist_hanlder возвращает предыдущий slist_hanlder. Это делает удобным установку и переустановку обработчиков ошибок на манер стека. В основном это может быть полезным в больших программах, в которых slist может использоваться в нескольких разных ситуациях, в каждой из которых могут, таким образом, задаваться свои собственные подпрограммы обработки ошибок. Например:

(* PFC old = set_slist_handler(my_handler);

// код, в котором в случае ошибок в slist // будет использоваться мой обработчик my_handler

set_slist_handler(old); // восстановление *)

Чтобы сделать управление более изящным, slist_hanlder мог бы быть сделан членом класса slist, что позволило бы раличным спискам иметь одновременно разные обработчики.

7.3.5 Обобщенные классы

Очевидно, можно было бы определить списки других типов (classdef*, int, char* и т.д.) точно так же, как был опредлен класс nlist: простым выводом из класса slist. Процесс оределения таких новых типов утомителен (и потому чреват ошиками), но с помощью макросов его можно «механизировать». К сожалению, если пользоваться стандартным C препроцессором (#4.7 и #с.11.1), это тоже может оказаться тягостным. Однако полученными в результате макросами пользоваться довольно просто.

Вот пример того, как обобщенный (generic) класс slist, названный gslist, может быть задан как макрос. Сначала для написания такого рода макросов включаются некоторые инстрменты из «generic.h»:

#include «slist.h»

#ifndef GENERICH #include «generic.h» #endif

Обратите внимание на использование #ifndef для того, чтобы гарантировать, что «generic.h» в одной компиляции не будет включен дважды. GENERICH определен в «generic.h».

После этого с помощью name2, макроса из «generic.h» для конкатенации имен, определяются имена новых обобщенных

классов:

#define gslist(type) name2(type,gslist) #define gslist_iterator(type) name2(type,gslist_iterator)

И, наконец, можно написать классы gslist(тип) и gslist_iterator(тип):

#define gslistdeclare(type) \ struct gslist(type) : slist (* \ int insert(type a) \ (* return slist::insert( ent(a) ); *) \ int append(type a) \ (* return slist::append( ent(a) ); *) \ type get (* return type( slist::get ); *) \ gslist(type) (* *) \ gslist(type)(type a) : (ent(a)) (* *) \ ~gslist(type) (* clear; *) \ *); \ \ struct gslist_iterator(type) : slist_iterator (* \ gslist_iterator(type)(gslist(type) amp; a) \ : ( (slist amp;)s ) (**) \ type operator \ (* return type( slist_iterator::operator ); *)\ *)

\ на конце строк указывает , что следующая строка явлется частью определяемого макроса.

С помощью этого макроса список указателей на имя, аналгичный использованному раньше классу nlist, можно определить так:

#include «name.h»

typedef name* Pname; declare(gslist,Pname); // описывает класс gslist(Pname)

gslist(Pname) nl; // описывает один gslist(Pname)

Макрос declare (описать) определен в «generic.h». Он конкатинирует свои параметры и вызывает макрос с этим именем, в данном случае gslistdeclare, описанный выше. Параметр имя типа для declare должен быть простым именем. Используемый мтод макроопределения не может обрабатывать имена типов вроде name*, поэтому применяется typedef.

Поделиться:
Популярные книги

Древесный маг Орловского княжества

Павлов Игорь Васильевич
1. Орловское княжество
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Древесный маг Орловского княжества

Закрытые Миры

Муравьёв Константин Николаевич
Вселенная EVE Online
Фантастика:
фэнтези
5.86
рейтинг книги
Закрытые Миры

Изгой

Майерс Александр
2. Династия
Фантастика:
фэнтези
попаданцы
рпг
аниме
5.00
рейтинг книги
Изгой

Менталист. Конфронтация

Еслер Андрей
2. Выиграть у времени
Фантастика:
боевая фантастика
6.90
рейтинг книги
Менталист. Конфронтация

Неучтенный элемент. Том 10

NikL
10. Антимаг. Вне системы
Фантастика:
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 10

Кодекс Охотника. Книга XXVII

Винокуров Юрий
27. Кодекс Охотника
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Охотника. Книга XXVII

Гримуар темного лорда IX

Грехов Тимофей
9. Гримуар темного лорда
Фантастика:
попаданцы
альтернативная история
аниме
фэнтези
5.25
рейтинг книги
Гримуар темного лорда IX

История Шотландии с древнейших времен до флодденского сражения 1513 года.

Скотт Вальтер
Научно-образовательная:
история
5.00
рейтинг книги
История Шотландии с древнейших времен до флодденского сражения 1513 года.

Тринадцатый VI

NikL
6. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Тринадцатый VI

Контрольный поцелуй

Донцова Дарья
8. Любительница частного сыска Даша Васильева
Детективы:
иронические детективы
9.15
рейтинг книги
Контрольный поцелуй

Бастард Императора. Том 4

Орлов Андрей Юрьевич
4. Бастард Императора
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Бастард Императора. Том 4

Отмороженный

Гарцевич Евгений Александрович
1. Отмороженный
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Отмороженный

Настольная книга по теологии. Библейский комментарий АСД Том 12

Церковь христиан адвентистов седьмого дня
Научно-образовательная:
религиоведение
5.00
рейтинг книги
Настольная книга по теологии. Библейский комментарий АСД Том 12

Темный Лекарь 9

Токсик Саша
9. Темный Лекарь
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Темный Лекарь 9