try-block
Associates one or more exception handlers (catch-clauses) with a compound statement.
Contents
[edit] Syntax
where handler-sequence is a sequence of one or more handler s, which have the following syntax:
catch ( attr (optional) type-specifier-seq declarator ) compound-statement | (1) |
catch ( attr (optional) type-specifier-seq abstract-declarator (optional) ) compound-statement | (2) |
catch ( . ) compound-statement | (3) |
compound-statement | — | brace-enclosed sequence of statements |
attr | — | (since C++11) any number of attributes, applies to the formal parameter |
type-specifier-seq | — | part of a formal parameter declaration, same as in a function parameter list |
declarator | — | part of a formal parameter declaration, same as in a function parameter list |
abstract-declarator | — | part of an unnamed formal parameter declaration, same as in function parameter list |
[edit] Explanation
A try-block is a statement, and as such, can appear anywhere a statement can appear (that is, as one of the statements in a compound statement, including the function body compound statement). See function-try-block for the try blocks around function bodies. The following description applies to both try-blocks and function-try-blocks.
The formal parameter of the catch clause ( type-specifier-seq and declarator or type-specifier-seq and abstract-declarator ) determines which types of exceptions cause this catch clause to be entered. It cannot be an incomplete type, abstract class type, rvalue reference type, (since C++11) or pointer to incomplete type (except that pointers to (possibly cv-qualified) void are allowed). If the type of the formal parameter is array type or function type, it is treated as the corresponding pointer type (similar to a function declaration).
When an exception is thrown by any statement in compound-statement , the exception object of type E is matched against the types of the formal parameters T of each catch-clause in handler-seq , in the order in which the catch clauses are listed. The exception is a match if any of the following is true:
- E and T are the same type (ignoring top-level cv-qualifiers on T )
- T is an lvalue-reference to (possibly cv-qualified) E
- T is an unambiguous public base class of E
- T is a reference to an unambiguous public base class of E
- T is (possibly cv-qualified) U or const U& (since C++14) , and U is a pointer or pointer to member type, and E is also a pointer or pointer to member type that is implicitly convertible to U by one or more of
- a standard pointer conversion other than one to a private, protected, or ambiguous base class
- a qualification conversion
- a function pointer conversion
- T is a pointer or a pointer to member or a reference to a const pointer (since C++14) , while E is std::nullptr_t .
try { f(); } catch (const std::overflow_error& e) {} // this executes if f() throws std::overflow_error (same type rule) catch (const std::runtime_error& e) {} // this executes if f() throws std::underflow_error (base class rule) catch (const std::exception& e) {} // this executes if f() throws std::logic_error (base class rule) catch (. ) {} // this executes if f() throws std::string or int or any other unrelated type
The catch-all clause catch ( . ) matches exceptions of any type. If present, it has to be the last catch clause in the handler-seq . Catch-all block may be used to ensure that no uncaught exceptions can possibly escape from a function that offers nothrow exception guarantee.
If no matches are found after all catch-clauses were examined, the exception propagation continues to the containing try-block, as described in throw-expression. If there are no containing try-blocks left, std::terminate is executed (in this case, it is implementation-defined whether any stack unwinding occurs at all: throwing an uncaught exception is permitted to terminate the program without invoking any destructors).
When entering a catch clause, if its formal parameter is a base class of the exception type, it is copy-initialized from the base class subobject of the exception object. Otherwise, it is copy-initialized from the exception object (this copy is subject to copy elision).
try { std::string("abc").substr(10); // throws std::length_error } // catch (std::exception e) // copy-initialization from the std::exception base // // std::cout // > catch (const std::exception& e) // reference to the base of a polymorphic object { std::coutwhat (); // information from length_error printed }
If the parameter of the catch-clause is a reference type, any changes made to it are reflected in the exception object, and can be observed by another handler if the exception is rethrown with throw ; . If the parameter is not a reference, any changes made to it are local and its lifetime ends when the handler exits.
Within a catch-clause, std::current_exception can be used to capture the exception in an std::exception_ptr , and std::throw_with_nested may be used to build nested exceptions. | (since C++11) |
A goto or switch statement shall not be used to transfer control into a try block or into a handler.
Other than by throwing or rethrowing the exception, the catch-clause after a regular try block (not function-try-block) may be exited with a return, continue, break, goto, or by reaching the end of its compound-statement . In any case, this destroys the exception object (unless an instance of std::exception_ptr exists that refers to it).
[edit] Notes
The throw-expression throw NULL ; is not guaranteed to be matched by a pointer catch clause, because the exception object type may be int , but throw nullptr ; is assuredly matched by any pointer or pointer-to-member catch clause.
If a catch-clause for a derived class is placed after the catch-clause for a base class, the derived catch-clause will never be executed:
try { f(); } catch (const std::exception& e) {} // will be executed if f() throws std::runtime_error catch (const std::runtime_error& e) {} // dead code!
If goto is used to exit a try-block and if any of the destructors of block-scoped automatic variables that are executed by the goto throw exceptions, those exceptions are caught by the try blocks in which the variables are defined:
label: try { T1 t1; try { T2 t2; if (condition) goto label; // destroys t2, then destroys t1, then jumps to label } catch (. ) {} // catches the exception from the destructor of t2 } catch (. ) {} // catches the exception from the destructor of t1
[edit] Keywords
[edit] Example
The following example demonstrates several usage cases of the try-catch block
#include #include int main() { try { std::cout "Throwing an integer exception. \n"; throw 42; } catch (int i) { std::cout " the integer exception was caught, with value: " i '\n'; } try { std::cout "Creating a vector of size 5. \n"; std::vectorint> v(5); std::cout "Accessing the 11th element of the vector. \n"; std::cout v.at(10); // vector::at() throws std::out_of_range } catch (const std::exception& e) // caught by reference to base { std::cout " a standard exception was caught, with message '" e.what() "'\n"; } }
Throwing an integer exception. the integer exception was caught, with value: 42 Creating a vector of size 5. Accessing the 11th element of the vector. a standard exception was caught, with message 'out_of_range'
[edit] Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 98 | C++98 | a switch statement can transfer control into a try block or into a handler | prohibited |
CWG 210 | C++98 | the throw expression was matched against the catch clauses | the exception object is matched against the catch clauses |
CWG 1166 | C++98 | the behavior was unspecified when a catch clause whose exception type is a reference to an abstract class type is matched | abstract class types are not allowed for catch clauses |
CWG 1769 | C++98 | when the type of the exception declared in the catch-clause is a base of the type of the exception object, a converting constructor might be used for the initialization of the catch-clause parameter | the parameter is copy-initialized from the corresponding base class subobject of the exception object |
CWG 2093 | C++98 | an exception object of pointer to object type could not match a handler of pointer to object type through qualification conversion | allowed |
Перехват исключений в Visual C++
В этой статье описывается try-catch-finally использование блока для перехвата исключения.
Исходная версия продукта: Visual C++
Исходный номер базы знаний: 815662
Аннотация
Блок try-catch-finally — это оболочка, которая помещается вокруг любого кода, в котором может возникнуть исключение. Перехват и работа с исключениями — это стандартные задачи программирования.
Блок try-catch-finally состоит из следующих разделов:
- Любой код, который может вызвать исключение, помещается в блок try.
- Если возникает исключение, catch вводится блок, и программа может выполнить соответствующую операцию для восстановления или оповещения пользователя.
- Код в блоке finally всегда выполняется и может выполнять очистку после возникновения исключения. Блок finally необязателен.
В этой статье рассматриваются следующие пространства имен библиотеки классов Microsoft платформа .NET Framework: System.IO и System.Security .
Перехват исключений в Visual C++ .NET
- Запустите Visual Studio .NET.
- В меню Файл выберите пункт Создать и затем пункт Проект.
- В Visual C++ щелкните Visual C++ в разделе Типы проектов, а затем выберите консольное приложение CLR в разделе Шаблоны.
- В поле Имя введите Q815662 и нажмите кнопку ОК.
- Замените весь код в окне кода Q815662.cpp следующим кодом. Код объявляет и инициализирует три переменные. Инициализация k вызывает ошибку.
#include "stdafx.h" #using #include using namespace System; void _tmain(void) < Console::WriteLine("We're going to divide 10 by 0 and see what happens. "); Console::WriteLine(); int i = 10; int j = 0; int k = i/j; //Error on this line. >
#include "stdafx.h" #using #include using namespace System; void _tmain(void) < try < Console::WriteLine("We're going to divide 10 by 0 and see what happens. "); Console::WriteLine(); int i = 10; int j = 0; int k = i/j; //Error on this line. >catch(. ) < Console::WriteLine("An error occurred."); >>
Примечание. Сообщение об ошибке catch из блока отображается вместо сообщения об ошибке системного исключения.
This statement is always printed.
#include "stdafx.h" #using #include using namespace System; void _tmain(void) < try < Console::WriteLine("We're going to divide 10 by 0 and see what happens. "); Console::WriteLine(); int i = 10; int j = 0; int k = i/j; //Error on this line. >catch(. ) < Console::WriteLine("An error occurred."); >__finally //This section is performed regardless of the above processing. < Console::WriteLine(); Console::WriteLine("This statement is always printed"); >>
#include "stdafx.h" #using #include using namespace System; using namespace System::Reflection; void _tmain(void) < try < Console::WriteLine("We're going to divide 10 by 0 and see what happens. "); Console::WriteLine(); int i = 10; int j = 0; int k = i/j; //Error on this line. >catch(Exception *e) < Console::WriteLine("An error occurred."); Console::WriteLine(e->Message); // Print the error message. Console::WriteLine(e->StackTrace); //String that contains the stack trace for this exception. > __finally //This section is performed regardless of the above processing. < Console::WriteLine(); Console::WriteLine("This statement is always printed"); >Console::ReadLine(); >
#include "stdafx.h" #using #include using namespace System; using namespace System::IO; using namespace System::Security; void _tmain(void) < try < File::Create("c:\\temp\\testapp.txt"); //Can fail for a number of resons >// This error may occur if the temp folder does not exist. catch(IOException *ioe) < Console::WriteLine("An IOException exception occurred!"); Console::WriteLine(ioe->ToString()); > // You do not have the appropriate permission to take this action. catch(SecurityException *se) < Console::WriteLine("An SecurityException exception occur") >// Catch all exceptions catch(Exception *e) < Console::WriteLine(e->ToString()); > >
Обратная связь
Были ли сведения на этой странице полезными?