- •ИСКЛЮЧЕНИЯ. СПЕЦИФИКАЦИЯ ИСКЛЮЧЕНИЙ
- •Любое необработанное исключение приводит к вызову функции terminate(), которая
- •Обработка ошибок
- •Пример. Обработка выхода за границы массива с помощью исключения
- •int& operator[](int i); int size(){return sz;}
- •int main() {
- •2) возвратить значение, трактуемое как "ошибка";
- •Вариант [2] можно реализовать не всегда, поскольку не всегда удается определить значение "ошибка".
- •Механизм особых ситуаций можно рассматривать как динамический аналог механизма контроля типов и проверки
- •Пример. Обработка двух исключений
- •Vector::Vector(int s) {
- •catch (Vector::Range) {
- •Примечание. Особые ситуации можно перехватывать в одной функции, можно в разных.
- •Передача данных при
- •class Range { public:
- •void f(int s, int i) { try {/*…*/}
- •2. Поддерживается окончательная модель обработки. Это означает, что после
- •5.Если обработчик «поймал» исключение, то обработка этого же исключения другими обработчиками, которые могут
- •Иерархия исключений
- •void f2() {
- •int main() { f2(); return 0;
- •int formula(int x, int y) {
- •int main() {
- •Особые ситуации могут быть членами нескольких групп.
- •void f3() {
- •int main() { f3(); f4();
Vector::Vector(int s) {
if (s<0 || max<s) throw Size(); p=new int[sz=s];
}
int& Vector::operator[](int i) {
if (0<=i && i<sz) return p[i]; throw Range();
}
void f(int s, int i) { try {
Vector v(s); v[i]=3;
cout<<"Вызов f\n";
}
catch (Vector::Range) {
cerr << "Ошибка в индексе
Vector::Range\n"; i=i%s; f(s,i);
}
catch (Vector::Size) {
cerr << "Ошибка в конструкторе Vector::Size\n";
}
}
int main() { f(-4,2); f(5,12);
return 0; }
Примечание. Особые ситуации можно перехватывать в одной функции, можно в разных.
Обработчики особых ситуаций могут быть вложенными.
Пример. Схема вложенного обработчика особых ситуаций
try { // ... } сatch (xxii) {
try {/* сложная реакция */} catch (xxii) {
/* ошибка в процессе сложной реакции */ }
}
Передача данных при |
обработке |
исключений |
|
Особая ситуация перехватывается благодаря своему типу, но при этом создаётся объект.
Если нужно передать некоторую информацию из точки запуска в обработчик, то для этого ее следует поместить в запускаемый объект через конструктор.
Пример. Передача индекса массива в исключение Range
class Vector {
…
class Range { public:
int index;
Range(int i) : index(i) { }
};
…
}
int& Vector::operator[](int i) {
if (0<=i && i<sz) return p[i]; throw Range(i);
}
void f(int s, int i) { try {/*…*/}
catch (Vector::Range r) {
cerr << "недопустимый индекс: " << r.index << '\n';
//…
}
//…
}
Особенности механизма обработки
исключений в языке C++
1. Обрабатываются только исключительные ситуации, явно генерируемые некоторой функцией.
2. Поддерживается окончательная модель обработки. Это означает, что после
возникновения исключения невозможно продолжение выполнения программы с точки исключения.
3.Обработка исключения возможна только в функции, вызванной до его возникновения и еще не завершившейся.
4.Если заявлено исключение, для которого нет обработчика в цепочке вызовов, программа будет завершена. В процессе поиска обработчика программный стек будет раскручен до конца.
5.Если обработчик «поймал» исключение, то обработка этого же исключения другими обработчиками, которые могут для него существовать, невозможна.
6.Если после заявления исключения управление передано catch-блоку, то вне зависимости от результата последующих действий исключение считается обработанным.
7.Обработчик может заявить исключение. В нём может использоваться оператор throw без параметра, что означает повторное генерирование исключения, обрабатываемого в данный момент.
Иерархия исключений
Часто исключения естественным образом группируются в семейства.
Пример. Обработка математических
исключений с помощью типа перечисления.
enum MathError {Overflow, Underflow, Zerodivide, /* ... */ };
int formula(int x, int y) {
if (y==0) throw Zerodivide;
if (x>2000000 || x<-2000000) throw Overflow; return x*x/y;
}
void f2() {
try {formula(300000,0);} catch(MathError m) {
switch (m) { case Overflow:
cerr<<"Переполнение\n"; break; case Underflow:
cerr<<"Исчезновение порядка\n"; break;
case Zerodivide:
cerr<<"Деление на 0\n"; break;
}
}
}