|
|
(39 intermediate revisions by 11 users not shown) |
Line 1: |
Line 1: |
− | {{title|try-block}}
| |
− | {{cpp/language/exceptions/navbar}}
| |
| | | |
− | Associates one or more exception handlers (catch-clauses) with a compound statement.
| |
− |
| |
− | ===Syntax===
| |
− | {{sdsc begin}}
| |
− | {{sdsc|1=
| |
− | {{ttb|try}} {{spar|compound-statement}} {{spar|handler-sequence}}
| |
− | }}
| |
− | {{sdsc end}}
| |
− |
| |
− | where {{spar|handler-sequence}} is a sequence of one or more {{spar|handler}}s, which have the following syntax:
| |
− |
| |
− | {{sdsc begin}}
| |
− | {{sdsc|num=1|1=
| |
− | {{ttb|catch}} {{ttb|(}} {{spar|attr}}{{mark optional}} {{spar|type-specifier-seq}} {{spar|declarator}} {{ttb|)}} {{spar|compound-statement}}
| |
− | }}
| |
− | {{sdsc|num=2|1=
| |
− | {{ttb|catch}} {{ttb|(}} {{spar|attr}}{{mark optional}} {{spar|type-specifier-seq}} {{spar|abstract-declarator}}{{mark optional}} {{ttb|)}} {{spar|compound-statement}}
| |
− | }}
| |
− | {{sdsc|num=2|1=
| |
− | {{ttb|catch}} {{ttb|(}} {{ttb|...}} {{ttb|)}} {{spar|compound-statement}}
| |
− | }}
| |
− | {{sdsc end}}
| |
− |
| |
− | {{par begin}}
| |
− | {{par | {{spar|compound-statement}} | the brace-enclosed {{rlp|statements#Compound_statement|sequence of statements}} that constututes the body of a function}}
| |
− | {{par | {{spar|attr}}{{mark c++11}} | optional list of {{rlp|attributes}}, applies to the formal parameter}}
| |
− | {{par | {{spar|type-specifier-seq}} | part of a formal parameter declaration, same as in a {{rlp|function}} parameter list }}
| |
− | {{par | {{spar|declarator}} | part of a formal parameter declaration, same as in a {{rlp|function}} parameter list }}
| |
− | {{par | {{spar|abstract-declarator}} | part of an unnamed formal parameter declaration, same as in {{rlp|function}} parameter list }}
| |
− | {{par end}}
| |
− |
| |
− | @1@ Catch-clause that declares a named formal parameter
| |
− | {{source|try { /* */ } catch(const std::exception& e) { /* */ }
| |
− | }}
| |
− | @2@ Catch-clause that declares an unnamed parameter
| |
− | {{source|try { /* */ } catch(const std::exception&) { /* */ }
| |
− | }}
| |
− | @3@ Catch-all handler, which is activated for any exception
| |
− | {{source|try { /* */ } catch(...) { /* */ }
| |
− | }}
| |
− |
| |
− | ===Explanation===
| |
− | :{{small|See {{rlp|throw | throw exceptions}} for more information about throw-expressions}}
| |
− |
| |
− | A try-block is a {{rlp|statements|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 {{rlp|function-try-block}} for the try blocks around function bodies. The following description applies to both try-blocks and {{rlp|function-try-block}}s.
| |
− |
| |
− | The formal parameter of the catch clause ({{spar|type-specifier-seq}} and {{spar|declarator}} or {{spar|type-specifier-seq}} and {{spar|abstract-declarator}}) determines which types of exceptions cause this catch clause to be entered. It cannot be an {{rlp|reference|rvalue reference type}}, {{rlp|abstract class}}, {{rlp|incomplete type}}, or pointer to incomplete type (except that pointers to (possibly {{rlp|cv}}-qualified) {{c|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 {{rlp|function|function declration}})
| |
− |
| |
− | When an exception of type {{tt|E}} is thrown by any statement in {{spar|compound-statement}}, it is matched against the types of the formal parameters {{tt|T}} of each catch-clause in {{spar|handler-seq}}, in the order in which the catch clauses are listed. The exception is a match if any of the following is true:
| |
− | * {{tt|E}} and {{tt|T}} are the same type (ignoring top-level cv-qualifiers on {{tt|T}})
| |
− | * {{tt|T}} is an lvalue-reference to (possibly cv-qualified) {{tt|E}}
| |
− | * {{tt|T}} is an unambiguous public base class of {{tt|E}}
| |
− | * {{tt|T}} is a reference to an unambiguous public base class of {{tt|E}}
| |
− | * {{tt|T}} is a (possibly cv-qualified) pointer or a reference to a (possibly cv-qualified) pointer, and {{tt|E}} is also a pointer, which is implicitly convertible to T either by
| |
− | :* a standard {{rlp|implicit_cast|pointer conversion}}
| |
− | :* a {{rlp|implicit_cast|qualification conversion}}
| |
− | * {{tt|T}} is a pointer or a pointer to member (or a reference to such pointer), while {{tt|E}} is {{lc|std::nullptr_t}}.
| |
− |
| |
− | {{source|
| |
− | 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 {{c|catch(...)}} matched exceptions of any type. If present, it has to be the last catch clause in the {{spar|handler-seq}}. Catch-all block may be used to ensure that no uncaught exceptions can possibly escape from a function that offers {{rlp|exceptions|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 {{rlp|throw|throw-expression}}. If there are no containing try-blocks left, {{lc|std::terminate}} is executed.
| |
− |
| |
− | When entering a catch clause, if its formal parameter is a base class of the exception type, it is {{rlp|copy_initialization|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 {{rlp|copy elision}}).
| |
− | {{source|1=
| |
− | try {
| |
− | std::string("abc").substr(10); // throws std::length_error
| |
− | // } catch( std::exception e ) { // copy-initialization from the std::exception base
| |
− | // std::cout << e.what(); // information from length_error is lost
| |
− | // }
| |
− | } catch( const std::exception& e ) { // reference to the base of a polymorphic object
| |
− | std::cout << e.what(); // information from length_error printed
| |
− | }
| |
− | }}
| |
− |
| |
− | If the parameter of the catch-clase 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 {{c|throw;}}. If the parameter is not a reference, any changes made to it are are local and its lifetime ends when the handler exits.
| |
− |
| |
− | {{rev begin}}
| |
− | {{rev |since=c++11|
| |
− | Within a catch-clause, {{lc|std::current_exception}} can be used to capture the exception in an {{lc|std::exception_ptr}}, and {{lc|std::throw_with_nested}} may be used to build nested exceptions.}}
| |
− | {{rev end}}
| |
− |
| |
− | ===Notes===
| |
− | The throw-expression {{c|throw NULL;}} is not matched by a pointer catch clause, because the exception object type is {{c|int}}, but {{c|throw nullptr;}} is 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.
| |
− | {{source|1=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 {{rlp|goto}} is used to exit a try-block and if any of the destructors of block-scoped automatic variables that are executed by the {{tt|goto}} throw exceptions, those exceptions are caught by the try blocks in which the variables are defined:
| |
− | {{source|1=
| |
− | 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
| |
− | }}
| |
− | ===Keywords===
| |
− |
| |
− | {{ltt|cpp/keyword/try}},
| |
− | {{ltt|cpp/keyword/catch}},
| |
− | {{ltt|cpp/keyword/throw}}
| |
− |
| |
− | ===Example===
| |
− | {{example
| |
− | | The following example demonstrates several usage cases of the {{tt|try-catch}} block
| |
− | | code=
| |
− | #include <iostream>
| |
− | #include <vector>
| |
− |
| |
− | 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::vector<int> 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";
| |
− | }
| |
− |
| |
− | }
| |
− | | output=
| |
− | 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'
| |
− | }}
| |
− |
| |
− | [[de:cpp/language/try catch]]
| |
− | [[es:cpp/language/try catch]]
| |
− | [[fr:cpp/language/try catch]]
| |
− | [[it:cpp/language/try catch]]
| |
− | [[ja:cpp/language/try catch]]
| |
− | [[pt:cpp/language/try catch]]
| |
− | [[ru:cpp/language/try catch]]
| |
− | [[zh:cpp/language/try catch]]
| |