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



         

Производные особые ситуации


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

class Matherr { // ... virtual void debug_print(); };

class Int_overflow : public Matherr { public: char* op; int opr1, opr2;; int_overflow(const char* p, int a, int b) { cerr << op << '(' << opr1 << ',' << opr2 << ')'; } };

void f() { try { g(); } catch (Matherr m) { // ... } }

При входе в обработчик Matherr особая ситуация m является объектом Matherr, даже если при обращении к g() была запущена Int_overflow. Это означает, что дополнительная информация, передаваемая в Int_overflow, недоступна.

Как обычно, чтобы иметь доступ к дополнительной информации можно использовать указатели или ссылки. Поэтому можно было написать так:

int add(int x, int y) // сложить x и y с контролем { if (x > 0 && y > 0 && x > MAXINT - y || x < 0 && y < 0 && x < MININT + y) throw Int_overflow("+", x, y);

// Сюда мы попадаем, либо когда проверка // на переполнение дала отрицательный результат, // либо когда x и y имеют разные знаки

return x + y; }

void f() { try { add(1,2); add(MAXINT,-2); add(MAXINT,2); // а дальше - переполнение } catch (Matherr& m) { // ... m.debug_print(); } }

Здесь последнее обращение к add приведет к запуску особой ситуации, который, в свою очередь, приведет к вызову Int_overflow::debug_print(). Если бы особая ситуация передавалась по значению, а не по ссылке, то была бы вызвана функция Matherr::debug_print().

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




Содержание  Назад  Вперед