Язык программирования C++ для профессионалов

       

Имена особых ситуаций


Особая ситуация перехватывается благодаря своему типу. Однако, запускается ведь не тип, а объект. Если нам нужно передать некоторую информацию из точки запуска в обработчик, то для этого ее следует поместить в запускаемый объект. Например, допустим нужно знать значение индекса, выходящее за границы диапазона:

class Vector { // ... public: class Range { public: int index; Range(int i) : index(i) { } }; // ... int& operator[](int i) // ... };

int Vector::operator[](int i) { if (o<=i && i <sz) return p[i]; throw Range(i); }

Чтобы исследовать недопустимое значение индекса, в обработчике нужно дать имя объекту, представляющему особую ситуацию:

void f(Vector& v) { // ...

try { do_something(v); } catch (Vector::Range r ) { cerr << "недопустимый индекс" << r.index << '\n'; // ... } // ... }

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

template<class T> class Allocator { // ... class Exhausted { } // ... T* get(); };

void f(Allocator<int>& ai, Allocator<double>& ad) { try { // ... } catch (Allocator<int>::Exhausted) { // ... } catch (Allocator<double>::Exhausted) { // ... } }

С другой стороны, особая ситуация может быть общей для всех созданных по шаблону классов:

class Allocator_Exhausted { };

template<class T> class Allocator { // ... T* get(); };

void f(Allocator<int>& ai, Allocator<double>& ad) { try { // ... } catch (Allocator_Exhausted) { // ... } }

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



Содержание раздела