Спецификации исключений
Спецификации исключений — это функция языка C++, которую не рекомендуется использовать в C++11. Они предназначались для предоставления сводных сведений об исключениях, которые может создавать функция, но на практике с этими спецификациями начали возникать проблемы. Действительно полезной оказалась лишь спецификация throw(). Например:
void MyFunction(int i) throw();
сообщает компилятору, что функция не создает исключений. Эта строка эквивалентна использованию атрибута __declspec (nothrow). Его использование не является обязательным. В стандарте ISO C++11 введен оператор noexcept, но поддержка этой функции пока отсутствует в Visual C++.
Visual C++ не соответствует стандарту ISO C++ при реализации спецификаций исключений. В следующей таблице представлены сводные сведения о реализации спецификаций исключений в Visual C++.
Спецификация исключений |
Значение |
---|---|
throw() |
Функция не вызывает исключений. Однако, если функция, помеченная атрибутом throw(), создает исключение, компилятор Visual C++ не вызывает функцию unexpected (дополнительные сведения см. в разделах unexpected (CRT) и unexpected (<exception>)). Если функция помечена атрибутом throw(), компилятор Visual C++ предполагает, что она не создает исключений C++, и формирует код соответствующим образом. Из-за оптимизации кода, которую может выполнять компилятор C++ (на основе допущения, что функция не создает исключений C++), создание исключения такой функцией может привести к неправильному выполнению программы. |
throw(...) |
Функция может создавать исключения. |
throw(type) |
Функция может создавать исключения типа type. Однако в .NET для Visual C++ это интерпретируется как throw(...). См. раздел Спецификаторы исключений функций. |
Если в приложении используется обработка исключений, в ней должна быть одна или несколько функций, которые обрабатывают создаваемые исключения. Все функции, вызываемые между функцией, вызывающей исключение, и функцией, которая обрабатывает это исключение, должны быть способны создавать исключения.
Поведение функции относительно создания исключений зависит от следующих факторов.
В какой среде выполняется компиляция функции — в C или C++.
Какой параметр компилятора /EH вы используете.
Задана ли явно спецификация исключений.
Явные спецификации исключений не разрешено использовать для функций C.
В следующей таблице приведены сводные сведения о поведении функции относительно создания исключений.
Функция |
/EHsc |
/EHs |
/EHa |
/EHac |
---|---|---|---|---|
Функция C |
throw() |
throw(...) |
throw(...) |
throw(...) |
Функция C++ без спецификации исключений |
throw(...) |
throw(...) |
throw(...) |
throw(...) |
Функция C++ со спецификацией исключений throw() |
throw() |
throw() |
throw(...) |
throw(...) |
Функция C++ со спецификацией исключений throw(...) |
throw(...) |
throw(...) |
throw(...) |
throw(...) |
Функция C++ со спецификацией исключений throw(type) |
throw(...) |
throw(...) |
throw(...) |
throw(...) |
Пример
// exception_specification.cpp
// compile with: /EHs
#include <stdio.h>
void handler() {
printf_s("in handler\n");
}
void f1(void) throw(int) {
printf_s("About to throw 1\n");
if (1)
throw 1;
}
void f5(void) throw() {
try {
f1();
}
catch(...) {
handler();
}
}
// invalid, doesn't handle the int exception thrown from f1()
// void f3(void) throw() {
// f1();
// }
void __declspec(nothrow) f2(void) {
try {
f1();
}
catch(int) {
handler();
}
}
// only valid if compiled without /EHc
// /EHc means assume extern "C" functions don't throw exceptions
extern "C" void f4(void);
void f4(void) {
f1();
}
int main() {
f2();
try {
f4();
}
catch(...) {
printf_s("Caught exception from f4\n");
}
f5();
}