Бьерн Страуструп. Язык программирования С++ Второе дополненное издание



Pdf көрінісі
бет167/256
Дата11.07.2022
өлшемі2,87 Mb.
#37591
1   ...   163   164   165   166   167   168   169   170   ...   256
9.1 Обработка ошибок 
Создатель библиотеки способен обнаружить динамические ошибки, но не представляет какой в общем 
случае должна быть реакция на них. Пользователь библиотеки способен написать реакцию на такие 
ошибки, но не в силах их обнаружить. Если бы он мог, то сам разобрался бы с ошибками в своей 
программе, и их не пришлось бы выявлять в библиотечных функциях. Для решения этой проблемы в 
язык введено понятие особой ситуации
Только недавно комитетом по стандартизации С++ особые ситуации были включены в стандарт языка, 
но на время написания этой книги они еще не вошли в большинство реализаций. 
Суть этого понятия в том, что функция, которая обнаружила ошибку и не может справиться с нею, 
запускает особую ситуацию, рассчитывая, что устранить проблему можно в той функции, которая прямо 
или опосредованно вызывала первую. Если функция рассчитана на обработку ошибок некоторого вида, 
она может указать это явно, как готовность перехватить данную особую ситуацию. 
Рассмотрим в качестве примера как для класса Vector можно представлять и обрабатывать особые 
ситуации, вызванные выходом за границу массива: 
class Vector { 
int* 
p; 
int sz; 
public: 
class Range { }; 
// класс для особой ситуации 
int& 
operator[](int 
i); 
// 
... 
}; 
Предполагается, что объекты класса Range будут использоваться как особые ситуации, и запускать их 
можно так: 
int& Vector::operator[](int i) 

if (0<=i && ithrow 
Range(); 

Если в функции предусмотрена реакция на ошибку недопустимого значения индекса, то ту часть 
функции, в которой эти ошибки будут перехватываться, надо поместить в оператор try. В нем должен 
быть и обработчик особой ситуации: 
void f(Vector& v) 

// 
... 
try 

do_something(v); // содержательная часть, работающая с v 

catch (Vector::Range) { 


Бьерн Страуструп.
Язык программирования С++ 
 
233 
// обработчик особой ситуации Vector::Range 
// если do_something() завершится неудачно, 
// нужно как-то среагировать на это 
// сюда мы попадем только в том случае, когда 
// 
вызов do_something() приведет к вызову Vector::operator[]() 
// из-за недопустимого значения индекса 

// 
... 

Обработчиком особой ситуации называется конструкция 
catch ( /* ... */ ) { 
// 
... 

Ее можно использовать только сразу после блока, начинающегося служебным словом try, или сразу 
после другого обработчика особой ситуации. Служебным является и слово catch. После него идет в 
скобках описание, которое используется аналогично описанию формальных параметров функции, а 
именно, в нем задается тип объектов, на которые рассчитан обработчик, и, возможно, имена 
параметров (см. $$9.3). Если в do_something() или в любой вызванной из нее функции произойдет 
ошибка индекса (на любом объекте Vector), то обработчик перехватит особую ситуацию и будет 
выполняться часть, обрабатывающая ошибку. Например, определения следующих функций приведут к 
запуску обработчика в f(): 
void do_something() 

// 
... 
crash(v); 
// 
... 

void crash(Vector& v) 

v[v.size()+10]; // искусственно вызываем ошибку индекса 

Процесс запуска и перехвата особой ситуации предполагает просмотр цепочки вызовов от точки 
запуска особой ситуации до функции, в которой она перехватывается. При этом восстанавливается 
состояние стека, соответствующее функции, перехватившей ошибку, и при проходе по всей цепочке 
вызовов для локальных объектов функций из этой цепочки вызываются деструкторы. Подробно это 
описано в $$9.4. 
Если при просмотре всей цепочки вызовов, начиная с запустившей особую ситуацию функции, не 
обнаружится подходящий обработчик, то программа завершается. Подробно это описано в $$9.7. 
Если обработчик перехватил особую ситуацию, то она будет обрабатываться и другие, рассчитанные на 
эту ситуацию, обработчики не будут рассматриваться. Иными словами, активирован будет только тот 
обработчик, который находится в самой последней вызывавшейся функции, содержащей 
соответствующие обработчики. В нашем примере функция f() перехватит Vector::Range, поэтому эту 
особую ситуацию нельзя перехватить ни в какой вызывающей f() функции: 
int ff(Vector& v) 

try 

f(v); // 
в f() будет перехвачена Vector::Range 

catch (Vector::Range) { // 
значит сюда мы никогда не попадем 
// 
... 




Бьерн Страуструп.
Язык программирования С++ 
 
234 


Достарыңызбен бөлісу:
1   ...   163   164   165   166   167   168   169   170   ...   256




©emirsaba.org 2024
әкімшілігінің қараңыз

    Басты бет