Обработчики должны выводить сообщения об ошибках, связанных с исключением, прежде, чем вызывать функцию abort()
(определенную в заголовке cstdlib
) для завершения функции main()
.
Упражнение 18.6. С учетом следующих типов исключений и директивы catch
напишите выражение throw
, создающее объект исключения, который может быть обработан каждым блоком catch
:
(a) class exceptionType { };
catch (exceptionType *pet) { }
(b) catch (...) { }
(c) typedef int EXCPTYPE;
catch (EXCPTYPE) { }
18.1.3. Блок try
функции и конструкторы
В принципе исключения могут произойти в любой точке программы. В частности, исключение может произойти в процессе инициализации в конструкторе. Инициализация в конструкторе выполняется прежде, чем его тело. Блок catch
в теле конструктора не может обработать исключение, которое было передано при инициализации, поскольку блок try
в теле конструктора еще не был задействован в момент передачи исключения.
Для обработки исключения, переданного при инициализации, конструктор следует оформить как try
функцииtry
block). Блок try
функции позволяет ассоциировать группу директив catch
с фазой инициализации конструктора (или фазой удаления деструктора), а равно с телом конструктора (или деструктора). В качестве примера заключим конструктор Blob()
(см. раздел 16.1.2) в блок try
функции:
template
Blob
data(std::make_shared
/*
} catch(const std::bad_alloc &e) { handle_out_of_memory(e); }
Обратите внимание на ключевое слово try
, предшествующее двоеточию, начинающему список инициализации конструктора, и фигурную скобку, формирующую (в данном случае пустое) тело конструктора. Обработчик, связанный с этим блоком try
, применяется для обработки исключения, переданного либо из списка инициализации, либо из тела конструктора.
Следует заметить, что исключение может произойти при инициализации параметров конструктора. Такие исключения не являются частью блока try
функции. Блок try
функции обрабатывает только те исключения, которые происходят, когда конструктор начнет выполняться. Как и при любом другом вызове функции, если исключение происходит во время инициализации параметра, оно является частью вызывающего выражения и обрабатывается в контексте вызывающей стороны.
try
функции.
Упражнение 18.7. Определите классы Blob
и BlobPtr
из главы 16 так, чтобы для их конструкторов использовались блоки try
функции.
18.1.4. Спецификатор исключения noexcept
И для пользователей, и для компилятора может быть полезно знать, что функция не будет передавать исключения. Это упрощает написание кода, вызывающего эту функцию. Кроме того, если компилятор знает, что никаких исключений не будет, он может (иногда) оптимизировать код, что недоступно при возможности передачи.
noexcept
. Ключевое слово noexcept
после списка параметров функции означает, что функция не будет передавать исключений:
void recoup (int) noexcept; //
void alloc(int); //
Эти объявления заявляют, что функция recoup()
не будет передавать исключений, а функция alloc()
могла бы. Считается, что к функции recoup()
применена
Спецификатор noexcept
должен присутствовать во всех объявлениях и в соответствующем определении функции или ни в одном из них. Спецификатор предшествует замыкающему типу (см. раздел 6.3.3). Спецификатор noexcept
можно определить также в объявлении и определении указателя на функцию. Он неприменим к псевдониму типа или определению типа (typedef
). В функции-члене спецификатор noexcept
следует за квалификатором const
или квалификатором ссылки, но предшествует квалификаторам final
, override
и = 0
у виртуальной функции.