Г. Шилтд - Самоучитель C++ (DJVU) (1114955), страница 50
Текст из файла (страница 50)
Однако в данном случае класс в(асй реализован как шаблон. Следовательно, в нем можно хранить объекты любого типа. В представленном ниже примере создаются стек символов и стек действительных чисел: // Здесь показан родовой стек ()1нс1нг(е <аозггеат> нз(ня патезрасе зссг ((<)егьпе ЯУЕ 10 // создание родового класса згаск (егпр]а1е <с1азз ЯсасКТуре> с1азз з1асК ( ЯасКТуре зссК(нгьв]; // содержит стек (нг воз; // индекс вершины стека рнЫъс. чоЫ 1п11() ( (оз - 0; ) //нннциалнзациястека чон( рнз(г (БсасКТуре сн); // поменгает объект в стек Я(асКТуре рср() ' // выталкивает объект из стека Глава ) ), шаблоны и обработка исключительных ситуаций 335 // Помещение объекта в стек 'сещр1асе <с1аяя БеасКТуре> чей зеасК<ЗъасКТуре>::рнзЬ(ЯкасКтуре оЬ) (Еоз==Я12Е) ( сопя « "Стек полон"; лепнкп; ) яссК(соя] = оЬ; Ьоз++; Выталкивание объекта из стека ьетпр1асе <с1аяя ВпасКТуре> ЗЕасКТуре зкасК<япасКТуре>::рор() Тй (соя==О) ( сопя « "Стек пуст"; леянтп О; // возврат нуля при пустом стеке ) поз лепптп зксК(соз] „ 1плп:аап ( ) Демонстратд<я символьных стеков ясасК<сЬал> з1, з2; // создание двух стеков 1пс 1 инициализация стеков з1.1п1Ь(); з2.1пТЕ(); з1.рпзЬ ('а')) з2,рпзЬ('х '); з1.рпяЬ('Ь'); з2.рпзЬ('у'); з1.ризЬ('с')/ з2.рпзЬ('г'); агою(1=0; 1<3; 1++) сонЬ « "Из стека 1:" « з1.рор() « "1п"; Гоп(1=0; 1<3; '++) соиЬ « "Из стека 2:" « з2.рор() « "Ы'; Демонстрация стеков со значениями типа с]опЬ1е япасК<с]опЬ1е> бз1, бя2; // создание двух стеков инициализация стеков <)з1.1пув(); <(з2.
1п1т (); 336 Самоучитель с)в1. риаЬ(1.1)," с)в2.ривЬ(2 .2); дв!.ривЬ(3. 3); с(в2.ривЬ(4.4); бв1.ривЬ(5.5); с(а2.ривЬ(б.б); Гоп(1=0; 1<3; 1+') сопс « " из стека 1:" « с(в1.рор() « "~п"; акоп(1=0; 1<3; 1~-+) соив << " Из стека 2:" << с(в2.рор() << "~п"; тевипп О; Как показано на примере класса в1аск (и предыдущего класса 1(з(), родовые функции и классы обеспечивают мощный инструмент экономии времени при программировании, поскольку они позволяют определить общую форму алгоритма, который затем можно использовать с данными любого типа. Таким образом, вы избегаете однообразных операций по созданию отдельных процедур для каждого типа данных, с которыми должен работать ваш алгоритм. 3.
Класс-шаблон может иметь более одного родового типа данных. Просто объявите все необходимые для класса типы данных внутри спецификации 1еп(- р!а1е, перечислив их через запятую. Например, в следующем коротком примере создается класс с двумя родовыми типами данных: // Здесь в определении класса используется два родовых типа данных ()Тпс1ис(е <1оавтеап> ив(пя патпеврасе ак<1; (етпр!а1е <с1авв Туре1, с1авв Туре2> с1авв вус1ааа туре1 Туре2 3; риЬ11с: тус1авз(Туре1 а, Туре2 Ь) ( 1 = а; 3 = Ь; ) 'когст аьои() ( соис « 1 « ' ' « 3 « '~п') )' Тп' тпатп () тус1ава<гпт., йоиЬ1е> оЬ1(10, 0.23); тус1авз<сЬап, сЬап *> оЬ2('Х', "Это проверка" ) оЬ|.аЬоы(); // вывод значений типа (пв и ЙоиЬ1е оЬ2.аЬоы(); // вывод значений типа сЬат и сЬат * После выполнения программы на экран выводится следующая информация: 10 0.23 х Это проверка Глава 11. Шаблоны и обработка исключительных ситуаций В программе объявлено два типа объектов. В объекте оЫ используются целое и значение двойной точности.
В объекте оЬ2 — символ и указатель на символ. В обоих случаях компилятор автоматически генерирует необходимые данные и функции в соответствии со способом создания объектов. 1. Если этого еще не сделано, откомпилируйте и выполните два примера программ с родовыми классами. Попытайтесь объявлять списки и/или стеки для разных типов данных. 2. Создайте и продемонстрируйте родовой класс, реализующий очередь. 3.
Создайте родовой класс шрв1, который при вызове конструктора делает следующее: выводит на экранстроку-приглашение, ° получает данные от пользователя, повторно выводит на экран строку-приглашение, если вводимые данные не соответствуют заданному диапазону. Объекты типа 1врв1 должны объявляться следующим образом: шрот оЬ 1" оероха приглашениеч, нин значение, нахс значение) Здесь сптвока приглаитеиие- это сообщение, появляющееся на экране в качестве приглашения для ввода. Минимальное и максимальное допустимые значения задаются с помошью параметров мин значение и макс значеиие соответственно.
(Тип данных, вводимых пользователем, будет тем же самым, что и тип значений мин значение и макс зиачекые.) 11.3. Обработка исключительных ситуаций С++ обеспечивает встроенный механизм обработки ошибок, называемый обработкой исключительньх ситуаций (ехсергюп йапй(пф. Благодаря обработке исключительных ситуаций можно упростить управление и реакцию на ошибки во время выполнения программ. Обработка исключительных ситуаций в С++ организуется с помощью трех ключевых слов; 1гу, са1сЬ и 1Ьгов. В самых общих словах, инструкции программы, во время выполнения которых вы хотите обеспечить обработку исключительных ситуаций, располагаются в блоке 1гу. Если исключительная ситуация (т. е. ошибка) имеет место внутри блока 1гу, она возбуждается (ключевое слово 1Ьгов'), перехватывается (ключевое слово са1сЬ) и обрабатывается.
Ниже поясняется приведенное здесь общее описание. Самоучитель С-и- Как уже отмечалось, любая инструкция, которая возбуждает исключительную ситуацию, должна выполняться внутри блока (гу. (Функции, которые вызываются из блока )(гу также могут возбуждать исключительную ситуацию.) Любая исключительная ситуация должна перехватываться инструкцией са(сЬ, которая располагается непосредственно за блоком (гу, возбуждавшем исключительную ситуацию.
Далее представлена основная форма инструкций тгу и сагсЬ: бту ( У У блок аовоузделвл лоключлеелълой ситуации са~сЬ ( суре1 акФ ( блок ыерелъвеа иокллчлеелълой ситуация ) сав г (еяма вкч) // блох лерехвата локлаяиючелълой ситуации са си (сураЗ алд) ~/ блох ыерекеаеа локлвчлеалълой ситуации ) сасс1 ( еурегг ать) блок перехвата иоклвмцвтелълой олчувцив Блок (гу должен содержать ту часть вашей программы, в который вы хотите отслеживать ошибки.
Это могут быть как несколько инструкций внутри одной функции, так и все инструкции внутри функции в(атвО (что естественно ведет к отслеживанию ошибок во всей программе). После того как исключительная ситуация возбуждена, она перехватывается соответствующей этой конкретной исключительной ситуации инструкцией са1сЬ, которая ее обрабатывает. С блоком ггу может быть связано более одной инструкции са(сЬ.
То, какая именно инструкция са(сй используется, зависит от типа исключительной ситуации. То есть, если тип данных, указанный в инструкции са(св, соответствует типу исключительной ситуации, выполняется данная инструкция са(сЬ. При этом все оставшиеся инструкции блока (гу игнорируются (т. е. сразу после того, как какая-то инструкция в блоке ггу вызвала появление исключительной ситуации, управление передается соответствующей инструкции са(сй, минуя оставшиеся инструкции блока (гу, — иримеч.
пер.). Если исключительная ситуация перехвачена, аргумент агя получает ее значение. Если вам не нужен доступ к самой исключительной ситуации, можно в инструкции сагсЬ указать только ее тип (уре, аргумент агу указывать не обязательно. Можно перехватывать ЗЭ9 Глава 11. Шаблоны и обработка исключительиыхситуаиий любые типы данных, включая и типы создаваемых вами классов.
Фактически в качестве исключительных ситуаций часто используются именно типы классов. Далее представлена основная форма инструкции 11)гож: ГОГОМ Исатааактаяьнаи СааакаЧКа; Инструкция агом должна выполняться либо внутри блока 1гу, либо в любой функции, которую этот блок вызывает (прямо или косвенно). Здесь искаимииега)гам ситуация — это возбуждаемая инструкцией йгои исключительная ситуация. Если вы возбуждаете исключительную ситуацию, для которой нет соответствующей инструкции са1сЬ, может произойти ненормальное завершение программы.
Если ваш компилятор функционирует в соответствии со стандартом Яапдап) С++, то возбуждение необрабатываемой исключительной ситуации приводит к вызову стандартной библиотечной функции 1егпппа1ео. По умолчанию для завершения программы функция 1ейша1е() вызывает функцию аЬог1(), однако при желании можно задать собственную процедуру завершения программы. За подробностями обращайтесь к справочной документации вашего компилятора.
1, В следуюшем очень простом примере показано, как в С++ функционирует система обработки исключительных ситуаций: /1 простой пример обработки исключительной ситуации бсьпс1пс)е<1овГюеата> пвгпд патеврасе аТФ тп- ваап() ( сопс « "начало' и"; с ту ( начало блока сту сопл « "внутри блока сгу~п"; питон 10; 1/ возбуждение оплибки сопб « "Эта инструкция выполнена не будет"; ) саос)'. (1по 1) ( / / перехват оклибки сопб « "перехвачена оквтбка номер: соне « 1 « со11 « "конец"; тепптп 0; Самоучитель После выполнения программы на экран будет выведено следующее: начало Внутри блока Сгу Перехвачена ошибка номер: 10 конец Внимательно изучите программу. Как видите, здесь имеется блок 1гу, содержащий три инструкции, и инструкция са1св ((п1 1), обрабатывающая исключительную ситуацию целого типа.
Внутри блока 1гу будут выполнены только две из трех инструкций — инструкции соп1 и 1вгои. После того как исключительная ситуация возбуждена, управление передается выражению са1св и выполнение блока 1гу завершается. Таким образом, инструкция са1св вызывается не явно, управление выполнением программы просто передается этой инструкции. (Для этого стек автоматически сбрасывается.) Следовательно, следующая за инструкцией 1(ггое инструкция сов1 не будет выполнена никогда. После выполнения инструкции са1св, управление программы передается следующей за ней инструкции. Тем не менее, обычно блок са1св заканчивают вызовом функции ехИО, аЬог10 или какой-либо другой функции, принудительно завершающей программу, поскольку, как правило, система обработки исключительных ситуаций предназначена для обработки катастрофических ошибок.
2. Как уже упоминалось, тип исключительной ситуации должен соответствовать типу, заданному в инструкции са1св. Например, в предыдущем примере, если изменить тип данных в инструкции са1сЬ иа доиЫе, то исключительная ситуация не будет перехвачена и будет иметь место ненормальное завершение программы. Это продемонстрировано в следующем фрагменте: // Этот пример работать не будет ((1пс1цбе <гозггеалй цк(пд патеарасе зсб; 1п( таьп () ( соц( « '*начало'~п"; сг'у ( начало блока сгу соцб « "Внутри блока югу~в"; ГЬгои 10; возбуждение ошибки соцб « "Эта инструкция вьполнена не будет"; сабсЬ (боцЫе 1) (' О Эта инструкция не будет работать с исключительной ситуацией целого типа соцс « "перехвачена ошибка номер: "р сорб « 1 « "'сп"; сонг « "конец"; гегцгп 0; Глава 1 !.