Бьерн Страуструп - Язык программирования С++. Главы 9-10
Страница 6. Имена особых ситуаций



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

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

        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) {
            // ...
         }
       }

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

 
« Предыдущая статья   Следующая статья »