Язык программирования C++. Вводный курс



              

Перехват всех исключений


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

void manip() {

   resource res;

   res.lock();       // захват ресурса

   // использование ресурса

   // действие, в результате которого возбуждено исключение

   res.release();    // не выполняется, если возбуждено исключение

}

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

// управление попадает сюда при любом возбужденном исключении

catch (...) {

   // здесь размещаем наш код

}

Конструкция catch(...)

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

void manip() {

   resource res;

   res.lock();

   try {

      // использование ресурса

      // действие, в результате которого возбуждено исключение

   }

   catch (...) {

      res.release();

      throw;

   }

   res.release();   // не выполняется, если возбуждено исключение

}

Чтобы гарантировать освобождение ресурса в случае, когда выход из manip()

происходит в результате исключения, мы освобождаем его внутри catch(...) до того, как исключение будет передано дальше. Можно также управлять захватом и освобождением ресурса путем инкапсуляции в класс всей работы с ним. Тогда захват будет реализован в конструкторе, а освобождение – в автоматически вызываемом деструкторе. (С этим подходом мы познакомимся в главе 19.)




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