Выбрать главу

#include <iostream>

using namespace std;

/* Функционирование блоков try/catch возобновляется при каждом входе в функцию.

*/

void Xhandler(int test)

{

 try {

  if(test) throw test;

 }

 catch(int i) {

  cout << "Перехват! Исключение №: " << i << '\n';

 }

}

int main()

{

 cout << "HAЧАЛО\n ";

 Xhandler (1);

 Xhandler (2);

 Xhandler (0);

 Xhandler (3);

 cout << "КОНЕЦ";

 return 0;

}

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

НАЧАЛО

Перехват! Исключение №:1

Перехват! Исключение №:2

Перехват! Исключение №:3

КОНЕЦ

Как видите, программа сгенерировала три исключения. После каждого исключения функция Xhandler() передавала управление в функцию main(). Когда она снова вызывалась, возобновлялась и обработка исключения.

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

Перехват исключений классового типа

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

// Использование класса исключений.

#include <iostream>

#include <cstring>

using namespace std;

class MyException {

 public:

  char str_what[80];

  MyException() { *str_what =0; }

  MyException(char *s) { strcpy(str_what, s);}

};

int main()

{

 int a, b;

 try {

  cout << "Введите числитель и знаменатель: ";

   cin >> а >> b;

  if( !b) throw MyException("Делить на нуль нельзя!");

  else

   cout << "Частное равно " << a/b << "\n";

 }

 catch (MyException e) {

  // перехват ошибки

  cout << e.str_what << "\n";

 }

 return 0;

}

Вот один из возможных результатов выполнения этой программы.

Введите числитель и знаменатель: 10 0

Делить на нуль нельзя!

После запуска программы пользователю предлагается ввести числитель и знаменатель. Если знаменатель равен нулю, создается объект класса MyException, который содержит информацию о попытке деления на нуль. Таким образом, класс MyException инкапсулирует информацию об ошибке, которая затем используется обработчиком исключений для уведомления пользователя о случившемся.

Безусловно, реальные классы исключений гораздо сложнее класса MyException. Как правило, создание классов исключений имеет смысл в том случае, если они инкапсулируют информацию, которая бы позволила обработчику исключений эффективно справиться с ошибкой и по возможности восстановить работоспособность программы.

Использование нескольких catch-инструкций

Как упоминалось выше, с try-блоком можно связывать не одну, а несколько catch-инструкций. В действительности именно такая практика и является обычной. Но при этом все catch-инструкции должны перехватывать исключения различных типов. Например, в приведенной ниже программе обеспечивается перехват как целых чисел, так и указателей на символы.