И.А. Волкова, А.В. Иванов, Л.Е. Карпов - Основы объектно-ориентированного программирования. Язык программирования С++ (ЧБ) (1114895), страница 14
Текст из файла (страница 14)
Однако указатели на абстрактные классы создавать можно.Несмотря на то, что абстрактный класс не является полноценным типом,ТВМ для него создается. При этом в ТВМ перечисляются все виртуальныефункции, в том числе и чистые виртуальные функции.В классе-наследнике чистая виртуальная функция может быть переопределена обычной виртуальной функцией с соответствующей заменой пустого значения на адрес данной функции в ТВМ класса-наследника.Класс-наследник абстрактного класса может также быть абстрактнымклассом, если в нем осталась (или была дополнительно введена) хотя бы одначистая виртуальная функция.12.Средства обработки ошибок, исключения и обработка исключенийАппарат обработки ошибок позволяет создавать надежно работающие программы, которые не завершаются аварийно в случае возникновения неожиданныхаварийных ситуаций. Такими аварийными ситуациями являются, например, отсутствие необходимого файла, блокировка записи информационной базы и т.
д.Для обработки исключительных ситуаций используются ключевые словаtry, catch и throw.Часть программы, при выполнении которой необходимо обеспечить обработку исключительных ситуаций, помещается в try-блок. В программе можетбыть произвольное количество произвольно вложенных друг в друга try-блоков.Если ошибка возникла внутри некоторого внутреннего try-блока (либо ввызванной из него функции), то с помощью инструкции throw возбуждаетсяисключительная ситуация. Сигнал о таком возбуждении будет перехвачен и обработан в теле функции-обработчика, расположенном после ключевого словаcatch.
Обработчики помещаются сразу после try- блока. При возникновенииисключительной ситуации управление передается в подходящий обработчик и вtry-блок не возвращается (действительно, при возникновении подобной ошибкипродолжение исполнения части алгоритма, содержащей данную ошибку, нецелесообразно, а часто, и просто бессмысленно).77Основные формы использования try, catch, throw:try {. .
.throw исключ_ситуация;. . .}catch(type){ /* . . . throw . . . */}. . .catch(type arg) { /* . . . throw . . . */}. . .catch(. . .){ /* . . . throw . . . */}Параметром инструкции throw является исключительная ситуация –объект некоторого типа, в частности, встроенного. Так, в качестве исключительной ситуации может быть диагностическое сообщение (то есть, строка) или число.Если обработчик не может до конца обработать исключительную ситуацию,то инструкция throw без параметров передает обработку объемлющемуtry-блоку (так называемый перезапуск перехваченного исключения).12.1.
Правила выбора обработчика исключенияПри возникновении исключительной ситуации обработчики catch просматриваются в порядке их следования. Срабатывает тот обработчик catch, типпараметра которого соответствует типу исключительной ситуации в инструкцииthrow.Обработчик с параметром базового типа перехватывает исключительнуюситуацию типа-наследника. Поэтому обработчик с параметром типа-наследникадолжен быть объявлен раньше объявления обработчика с параметром базовоготипа.Аргумент arg при начале работы обработчика получает значение исключительной ситуации, указываемой в инструкции throw. Его можно использоватьв теле обработчика.
Обработчик catch(...) перехватывает все исключительные ситуации. Поэтому он должен быть последним в списке обработчиков.Если для исключительной ситуации не описан подходящий обработчик после соответствующего блока try, то данная ситуация перехватывается обработчиком для объемлющего try-блока.Если подходящий обработчик не найден во всех объемлющих try-блоках,то выполняется стандартная функция terminate(), которая по завершенииработы вызывает стандартную функцию abort(), аварийно завершающую работу программы.При описании функции можно указать типы исключительных ситуаций(спецификация исключений), которые может возбуждать функция:ИмяТип_возвра щаемогоформальныесписокфункции ( параметры ) throw ( типов );значения78Если список после ключевого слова throw пуст, то функция не может возбуждать исключительных ситуаций с помощью инструкции throw (ни прямо, никосвенно).Пример:void f1() throw(int, over_flow);void noexcp(int i) throw();Если в прототипе функции отсутствует ключевое слово throw, то функцияможет возбуждать любое исключение.При нарушении спецификации исключений, выполняется стандартнаяфункция unexpected(), аварийно завершающая программу.Блок try может содержать фрагмент программы, в котором объявляютсяобъекты.
При этом в конструкторах классов для данных объектов могут возбуждаться исключительные ситуации в случае невозможности корректного созданияобъекта по передаваемым параметрам. В этом случае в подходящем обработчикедля данного try-блока возможно корректно обработать ситуацию невозможности создания объекта.Пример:#include <iostream>using namespace std;class vect{int* p;int size;public:vect (int n):size (n){if (n < 1)throw n;p = new int [n];if (p == 0)throw "no free memory";};~vect () {delete[] p;}// . .
.};int g(int m){try {vect a(m);}catch (int n){cout << "error of size " <<n << '\n';79return 1;}catch (const char* er){cout << er << '\n';return 2;};// . . .return 0;}int main(){int ierr;int m;// . . .ierr = g (5);. . .ierr = g (0);// . . .ierr = g (m);// . . .return 0;}12.2.Стандартные исключения.Стандартные исключения – типы данных (классы или структуры), описывающие некоторые предопределенные исключительные ситуации, в частности,они могут составлять иерархию типов.Стандартные исключения могут быть включены в состав компиляторов C++или поставляться вместе со стандартной библиотекой.
Обычно, соответствующиеклассы и структуры содержатся в текстовых заголовочных файлах, например, в<exception>, <excpt.h> и других аналогичных, которые подключаются явноили неявно директивой препроцессора #include.Стандартные исключения, описанные классом или структурой, содержатвнутренние информационные члены, которые могут быть проанализированы, атакже собственные конструкторы, деструкторы и необходимые методы.12.3.Последовательность действий при возникновении исключительной ситуации.1) Создание временного объекта – копии исключительной ситуации.2) Уничтожение объектов, созданных в try-блоке, с запуском для них необходимых деструкторов, освобождающих динамическую память(свертка стека).3) Выход из try-блока.4) Подбор и выполнение обработчика для данного try-блока в соответствиис типом исключительной ситуации (статическая ловушка).805) Если необходимый обработчик для данного try-блока не найден или вобработчике имеется инструкция throw без параметров, сигнализирующая о незавершенности обработки исключительной ситуации, топроисходит выход в объемлющий try-блок с повторением пунктов 2-4(динамическая ловушка).6) Если исключительная ситуация осталась необработанной после выходаиз всех объемлющих try-блоков, то вызывается функцияterminate().13.Множественное наследование, интерфейсыМножественное наследование возникает, когда имеется несколько базовыхтипов и один тип – наследник.
При множественном наследовании появляетсявозможность моделирования более сложных отношений между типами.class X { . . . };class Y { . . . };class Z: public X, public Y { . . . };При описании производного класса каждый базовый класс имеет свой собственный описатель типа наследования (явно указанный или неявно предполагаемый) .13.1.Видимость при множественном наследовании.При множественном наследовании возникает проблема неоднозначностииз-за совпадающих имен в базовых классах.Пример:struct X {int i1;int jx;};struct Y {int i1;int jy;};struct Z: X, Y {int jz;};int main(){Z z1;z1.i1 = 5;// ошибка – неоднозначность: член i1// наследуется как из базового типа X, так81return 0;// и из базового типа Y.}Тем не менее, данная неоднозначность проявляется не при объявленииобъекта типа-наследника, а при использовании его членов, имеющихся в нескольких базовых типах.
Эту неоднозначность можно обойти при помощи операции разрешения области видимости:z1.X::i1 = 5Таким образом, в тип-наследник попадают все члены базовых типов. Ноповторяющиеся имена необходимо сопровождать квалификатором базового типа.13.2.Виртуальные базовые классыПри многоуровневом множественном наследовании базовые классы могутбыть получены от общего предка. В этом случае итоговый производный классбудет содержать несколько подобъектов общего предка:class W{ . . .};class X: public W{ . . . };class Y: public W{ . . . };class Z: public X, public Y{ .
. . };Если необходимо, чтобы общий предок присутствовал в итоговом производном классе в единственном экземпляре (например, если необходимо, чтобыфункции классов X и Y в классе Z использовали общие информационные членыкласса W, или для экономии оперативной памяти), то наследование базовыхклассов от общего предка описывается с использованием виртуального наследования:82class W{ . .