Файл: Pobegaylo_A._C_Cplus_dlya_studenta.pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 13.12.2020

Просмотров: 4287

Скачиваний: 28

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

Часть II. Язык программирования С++ 

166 

Для  работы  механизма  обработки  исключений  в  программе 
должны быть определены блоки 

try

 и 

catch

, которые организова-

ны следующим образом: 

  try 
  { 
    // тело блока try 
  } 
  catch(тип_исключения) 
  { 
    // тело блока catch 
  } 

Тело  блока 

try

  содержит  код,  при  исполнении  которого  может 

произойти выброс исключения, а тело блока 

catch

 содержит код, 

который  обрабатывает  исключение  и  поэтому  также  называется 

обработчиком исключения

. Отметим, что блок 

catch

 должен сле-

довать непосредственно за блоком 

try

Работает  механизм  обработки  исключений  следующим  образом. 
Если внутри блока 

try

 произошел выброс исключения, посредст-

вом  исполнения  инструкции  с  выражением 

throw

  внутри  этого 

блока  или  внутри  любой  функции,  которая  вызывается  в  этом 
блоке,  то  исполнение  блока 

try

  немедленно  прекращается  неза-

висимо  от  уровня  вложенности,  на  котором  произошел  выброс 
исключения,  а  управление  передается  блоку 

catch

.  После  завер-

шения работы блока 

catch

 управление передается на первую ин-

струкцию,  следующую  за  этим  блоком.  При  этом  блок 

catch

  

обрабатывает  только  то  исключение,  тип  которого  соответст- 
вует  его 

типу_исключения

.  Для  упрощения  терминологии 

тип_ 

исключения

  часто  также  называют 

типом  обработчика  исклю- 

чения

В  листинге  13.1  приведен  пример  обработки  исключения,  кото-
рое генерируется при попытке целочисленного деления на ноль. 

Листинг 13.1. Обработка исключения 

#include <iostream> 
using namespace std; 


background image

Глава 13. Обработка исключений 

167 

int divide(int a, int b) 

  if (!b) 
    throw "Zero divide"; 
  return a / b; 

int main() 

  int n, m; 
  try 
  { 
    // введите два целых числа через пробел 
    cout << "Input two integers: "; 
    cin >> n >> m; 
    cout << "n/m = " << divide(n,m) << endl; 
  } 
  catch(char* str) 
  { 
    cout << str << endl;  // печатает: Zero divide 
  } 
  cout << "OK" << endl; 
 
  return 0; 

Кратко  поясним  работу  этой  программы.  Пользователь  вводит 
два целых числа. Если делитель не равен нулю, то программа пе-
чатает  частное  от  деления  этих  чисел,  которое  вычисляется 
функцией 

divide

. Тонкость в том, что функция 

divide

 проверяет 

делитель на равенство нулю. Если он равен нулю, то функция не 
вычисляет частное, а выбрасывает исключение "

Zero divide

" ти-

па 

char*

. Если исключение выброшено, то как исполнение функ-

ции 

divide

, так и исполнение блока 

try

 немедленно завершается, 

а  управление  передается  в  блок 

catch

.  Для  этого  тип  параметра 

блока 

catch

  выбран  в  соответствии  с  типом  выбрасываемого  ис-

ключения. 
Часто  при  обработке  исключения  нужно  знать  только  тип  этого 
исключения.  В  этом  случае  для  типа  исключения  используют 


background image

Часть II. Язык программирования С++ 

168 

пустые  структуры.  Например,  в  нашем  случае  можно  было  бы 
определить исключение типа 

  struct ZeroDivide{};

 

Программа  обработки  такого  исключения  приведена  в  листин-
ге 13.2. Заметим, что в этой программе инструкция с выражением 

throw

 выбрасывает объект типа 

ZeroDivide

, а не сам тип. Для это-

го используется конструктор по умолчанию структуры 

ZeroDivide

Листинг 13.2. Обработка исключения (используя пустой тип) 

#include <iostream> 
using namespace std; 
struct ZeroDivide {}; 
int divide(int a, int b) 

  if (!b) 
    throw ZeroDivide(); 
  return a / b; 

int main() 

  int n, m; 
  try 
  { 
    // введите два целых числа через пробел 
    cout << "Input two integers: "; 
    cin >> n >> m; 
    cout << "n/m = " << divide(n,m) << endl; 
  } 
  catch(ZeroDivide) 
  { 
    cout << "Zero divide" << endl;  // печатает: Zero divide 
  } 
  cout << "OK" << endl; 
 
  return 0; 


background image

Глава 13. Обработка исключений 

169 

В  заключение  этого  раздела  скажем,  что  для  выхода  из  блоков 

try

 и 

catch

 можно использовать инструкции передачи управления 

return

break

continue

  и 

goto

. Невозможно передать управление 

внутрь блоков 

try

 или 

catch

, используя инструкцию 

goto

13.2. Обработка  
нескольких исключений 

Для обработки исключений разных типов допускается использо-
вание  нескольких  последовательных  блоков 

catch

.  Если  внутри 

блока 

try

 произошел выброс исключения, то управление переда-

ется  первому  обработчику  исключения,  тип  которого  соответст-
вует  типу  выброшенного  исключения.  Если  такого  обработчика 
нет,  то  вызывается  функция 

terminate

,  которая  в  свою  оче- 

редь  вызывает  функцию 

abort

,  которая  и  завершает  исполнение 

программы.  Подробно  работа  этими  функциями  рассмотрена  
в 

гл. 36

После  обработки  исключения  управление  передается  на  первую 
инструкцию, которая следует за последним обработчиком исклю-
чения. 
В листинге 13.3 приведена программа, в которой обрабатываются 
два типа исключений. 

Листинг 13.3. Обработка исключений двух типов 

#include <iostream> 
using namespace std; 
struct ZeroDivide {}; 
int divide(int a, int b) 

  int r;  // остаток от деления 
  if (!b) 
    throw ZeroDivide(); 
  r = a % b; 
  if (r) 
    throw r; 


background image

Часть II. Язык программирования С++ 

170 

  return a / b; 

int main() 

  int n, m; 
  try 
  { 
    // введите два целых числа через пробел 
    cout << "Input two integers: "; 
    cin >> n >> m; 
    cout << "n/m = " << divide(n,m) << endl; 
  } 
  catch(ZeroDivide) 
  { 
    cout << "Zero divide" << endl;  // печатает: Zero divide 
  } 
  catch(int &r) 
  { 
    cout << "Remainder = " << r << endl;  // печатает остаток 
  } 
  cout << "OK" << endl; 
 
  return 0; 

13.3. Перехват всех исключений 

Для перехвата исключений любого типа используется обработчик 
исключения, который имеет следующий вид: 

  catch(...) 
  { 
    // тело блока catch 
  } 

Очевидно, что если такой обработчик исключений используется, 
то  он  должен  быть  последним  в  последовательности  обработ- 
чиков  исключений.  Иначе  он  будет  перехватывать  все  исклю- 
чения. 


Смотрите также файлы