Основы обработки исключительных ситуаций
Обработка исключительных ситуаций лишена недостатков вышеназванных методов реагирования на ошибки. Этот механизм позволяет использовать для представления информации об ошибке объект любого типа. Поэтому можно, например, создать иерархию классов, которая будет предназначена для обработки аварийных событий. Это упростит, структурирует и сделает более понятной программу.
Рассмотрим пример обработки исключительных ситуаций. Функция div() возвращает частное от деления чисел, принимаемых в качестве аргументов. Если делитель равен нулю, то генерируется исключительная ситуация.
#include<iostream>
using namespace std;
double div(double dividend, double divisor)
{ if(divisor==0) throw 1;
return dividend/divisor;
}
int main()
{ double result;
try {
result=div(77.,0.);
cout<<"Answer is "<<result<<endl;
}
catch(int){
cout<<"Division by zero"<<endl;
}
return 0;
}
Результат выполнения программы:
Division by zero
В данном примере необходимо выделить три ключевых элемента. Во-первых, вызов функции div() заключен внутрь блока, который начинается с ключевого слова try. Этот блок указывает, что внутри него могут происходить исключительные ситуации. По этой причине код, заключенный внутри блока try, иногда называют охранным.
Далее за блоком try следует блок catch, называемый обычно обработчиком исключительной ситуации. Если возникает исключительная ситуация, выполнение программы переходит к этому catch-блоку. Хотя в этом примере имеется один-единственный обработчик, их в программах может быть множество и они способны обрабатывать множество различных типов исключительных ситуаций.
Еще одним элементом процесса обработки исключительных ситуаций является оператор throw (в данном случае он находится внутри функции div()). Оператор throw сигнализирует об исключительном событии и генерирует объект исключительной ситуации, который перехватывается обработчиком catch. Этот процесс называется вызовом исключительной ситуации. В рассматриваемом примере исключительная ситуация имеет форму обычного целого числа, однако программы могут генерировать практически любой тип исключительной ситуации.
Если в инструкции if(divisor==0) throw 1 значение 1 заменить на 1. , то при выполнении будет выдана ошибка об отсутствии соответствующего обработчика catch (так как возбуждается исключительная ситуация типа double).
Одним из главных достоинств использования механизма обработки исключительных ситуаций является обеспечение развертывания стека. Развертывание стека – это процесс вызова деструкторов локальных объектов, когда исключительные ситуации выводят их из области видимости.
Сказанное рассмотрим на примере функции add() класса add_class, выполняющей сложение компонентов-данных объектов add_class и возвращающей суммарный объект. В случае, если сумма превышает максимальное значение для типа unsigned short, генерируется исключительная ситуация.
#include<iostream>
using namespace std;
#include<limits.h>