Блок-try-функции
Устанавливает обработчик исключений вокруг тела функции.
Синтаксис
Блок-try-функции это одна из альтернативных форм синтаксиса для тела-функции, которая является частью определение функции.
try инициализатор-конструктора (необязательно) составное-выражение последовательность-обработчиков
|
|||||||||
| инициализатор-конструктора | — | список инициализаторов элементов, разрешённый только в конструкторах |
| составное-выражение | — | заключённая в фигурные скобки последовательность операторов, составляющая тело функции |
| последовательность-обработчиков | — | последовательность из одного или нескольких предложений catch |
Объяснение
Блок-try-функции связывает последовательность предложений catch со всем телом функции, а также со списком инициализаторов элементов (если используется в конструкторе). Каждое исключение, брошенное из любого оператора в теле функции, или (для конструкторов) из любого элемента или базового конструктора, или (для деструкторов) из любого элемента или базового деструктора, передаёт управление последовательности-обработчиков так же, как исключение, брошенное в обычном блоке try.
#include <iostream>
#include <string>
struct S
{
std::string m;
S(const std::string& str, int idx) try : m(str, idx)
{
std::cout << "S(" << str << ", " << idx << ") построен, m = " << m << '\n';
}
catch(const std::exception& e)
{
std::cout << "S(" << str << ", " << idx << ") потерпел крах: " << e.what() << '\n';
} // здесь неявный "throw;" для конструктора
};
int main()
{
S s1{"ABC", 1}; // не бросает (индекс в пределах допустимого)
try
{
S s2{"ABC", 4}; // бросает (выход за границы)
}
catch (std::exception& e)
{
std::cout << "S s2... вызывает исключение: " << e.what() << '\n';
}
}
Прежде чем будут введены какие-либо предложения catch блока-try-функции в конструкторе, все полностью сконструированные элементы и базовые классы уже будут уничтожены.
|
Если блок-try-функции находится в конструкторе делегирования, который вызвал конструктор без делегирования, который завершился успешно, но затем тело конструктора делегирования вызывает исключение, деструктор этого объекта будет завершён до любых предложений catch блока-try-функции. |
(начиная с C++11) |
Прежде чем будут введены какие-либо предложения catch блока-try-функции в деструкторе, все базовые и невариантные элементы уже будут уничтожены.
Поведение не определено, если предложение catch блока-try-функции, используемого в конструкторе или деструкторе, обращается к базовому классу или нестатическому элементу объекта.
Каждое предложение catch в блоке-try-функции для конструктора должно завершаться выдачей исключения. Если управление достигает конца такого обработчика, текущее исключение автоматически выбрасывается снова, как будто через throw;. Оператор return не допускается ни в одном предложении catch блока-try-функции конструктора.
Достижение конца предложения catch для блока-try-функции в деструкторе также автоматически повторно выдаёт текущее исключение, как будто с помощью throw;, но допускается оператор return.
Для всех других функций достижение конца предложения catch эквивалентно return;, если возвращаемый тип функции (возможно, cv-квалифицированный) void, иначе поведение не определено.
Примечание
Основная цель блоков-try-функций состоит в том, чтобы реагировать на исключение, созданное из списка инициализаторов элементов в конструкторе, путём регистрации и повторного создания, изменения объекта исключения и повторного создания, создания вместо него другого исключения или завершения программы. Они редко используются с деструкторами или с обычными функциями.
Блок-try-функции не перехватывает исключения, генерируемые конструкторами копирования/перемещения и деструкторами параметров функции, передаваемых по значению: эти исключения генерируются в контексте вызывающего объекта.
| Блок-try-функции верхнего уровня потока не перехватывает исключения, генерируемые конструкторами и деструкторами локальных объектов потока (за исключением конструкторов локальных объектов потока в области видимости функции). | (начиная с C++11) |
Аналогично, блок-try-функции main() не перехватывает исключения, генерируемые конструкторами и деструкторами статических объектов (за исключением конструкторов статических локальных объектов функции).
Область видимости и время жизни параметров функции (но не любых объектов, объявленных в самой функции), распространяются до конца последовательности-обработчиков.
int f(int n = 2) try
{
++n; // инкрементирует параметр функции
throw n;
}
catch(...)
{
++n; // n находится в области видимости и по-прежнему ссылается на параметр функции
assert(n == 4);
return n;
}
Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
| Номер | Применён | Поведение в стандарте | Корректное поведение |
|---|---|---|---|
| CWG 1167 | C++98 | не было указано, будет ли блок-try-функции в деструкторе перехватывать исключения из базового деструктора или деструктора-элемента |
такие исключения перехватываются |