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

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


Назад  |  Вперёд


OtDiatlovaOU
К началу книги

Оформление и дизайн книги OtDiatlovaOU.
Вся книга, архив.