printИсключительные ситуации

printПорождение и перехват

Для порождения исключений используется оператор
throw выражение;
Рекомендуется указывать в качестве аргумента объекты специальных классов, а не стандартных типов (int) или классов общего назначения (vector). Классы исключений рекомендуется выстраивать в иерархии.

Операторы, которые могут генерировать исключения, записываются внутри блока try, после которого идет набор обработчиков исключений catch. У каждого обработчика указывается тип исключений, который он может перехватывать, и опционально имя, с помощью которого можно обращаться к созданному оператором throw объекту внутри обработчика.
Перехват исключения рекомендуется делать по ссылке, чтобы избежать срезки объекта при преобразовании к базовому классу.
try 
{ // операторы
}
catch(bad_alloc &)
{ // обработка ошибки выделения памяти
}
catch(io_error & e)
{ e.stream.clear(); // обработка ошибки ввода-вывода
}
catch(exception &)
{ // обработка других стандартных исключений 
}

Порядок обработки исключений следующий:
  • Создается копия аргумента throw в статической памяти.
  • Происходит поиск подходящего обработчика. В процессе поиска выполняется раскрутка стека, т.е. выход из функций, где нет подходящих обработчиков и вызов деструкторов для локальных объектов.
  • Если подходящий обработчик найден, управление передается ему, иначе вызывается функция terminate, которая по умолчанию аварийно завершает программу, но можно задать другое действие с помощью функции set_terminate
  • После выполнения обработчика копия аргумента throw в статической памяти уничтожается и управление передается на оператор, следующий за последним из обработчиков того набора, где был найден обработчик.
Если обработчик не смог полностью обработать исключение, то можно повторно сгенерировать исключение внутри обработчика с помощью оператора
throw;
Проверка на соответствие типа объекта и обработчика выполняется в порядке перечисления обработчиков, поэтому обработчики для исключений производных классов должны быть указаны до обработчиков базовых классов. Самым последним обработчиком в наборе может быть указан catch(...), который перехватывает все исключения. Такой обработчик можно использовать для корректного освобождения ресурсов:
int g(int n)
{
  int * a;
  a=new int[n];
  try
  { // ...
  }
  catch(...)
  { delete[] a;
    throw;
  }
  delete[] a;
}
Если функция не возвращает исключений, то можно указать это в заголовке:
void f() noexcept;
Рекомендуется, чтобы деструктор не возвращал исключений, так как деструкторы вызываются при раскрутке стека и возникновение исключений в этот момент приведет к вызову terminate и аварийному завершению программы.
loading