the handler is of type cvT or const T&
where T is a pointer or pointer-to-member type and
E is a pointer or pointer-to-member type
that can be converted to T by one or more of
A
throw-expression
whose operand is an integer literal with value zero does not match a handler of
pointer or pointer-to-member type.
A handler of reference to array or function type
is never a match for any exception object ([expr.throw]).
— end note]
[Example 1: class Matherr {/* ... */virtualvoid vf(); };
class Overflow:public Matherr {/* ... */};
class Underflow:public Matherr {/* ... */};
class Zerodivide:public Matherr {/* ... */};
void f(){try{
g();
}catch(Overflow oo){// ...}catch(Matherr mm){// ...}}
Here, the
Overflow
handler will catch exceptions of type
Overflow
and the
Matherr
handler will catch exceptions of type
Matherr
and of all types publicly derived from
Matherr
including exceptions of type
Underflow
and
Zerodivide.
This makes it possible to write handlers that can never be
executed, for example by placing a handler for a final derived class after
a handler for a corresponding unambiguous public base class.
If no match is found among the handlers for a try block,
the search for a matching
handler continues in a dynamically surrounding try block
of the same thread.
If the search for a handler
encounters the outermost block of a function with a
non-throwing exception specification,
the function std::terminate ([except.terminate]) is invoked.
An implementation is not permitted to reject an expression merely because, when
executed, it throws or might
throw an exception from a function with a non-throwing exception specification.
— end note]
[Example 2: externvoid f(); // potentially-throwingvoid g()noexcept{
f(); // valid, even if f throwsthrow42; // valid, effectively a call to std::terminate}
The call to
f
is well-formed despite the possibility for it to throw an exception.
If no matching handler is found,
the function std::terminate is invoked;
whether or not the stack is unwound before this invocation of
std::terminate
is implementation-defined ([except.terminate]).
Referring to any non-static member or base class of an object
in the handler for a
function-try-block
of a constructor or destructor for that object results in undefined behavior.
Exceptions thrown in destructors of objects with static storage duration or in
constructors of objects associated with non-block variables with static storage duration are not caught by a
function-try-block
on
the main function.
Exceptions thrown in destructors of objects with thread storage duration or in constructors of objects associated with non-block variables with thread storage duration are not caught by a
function-try-block
on the initial function of the thread.
if T is a base class of E,
the variable is copy-initialized ([dcl.init])
from an lvalue of type T designating the corresponding base class subobject
of the exception object;
otherwise, the variable is copy-initialized ([dcl.init])
from an lvalue of type E designating the exception object.
The lifetime of the variable ends
when the handler exits, after the
destruction of any objects with automatic storage duration initialized
within the handler.
When the handler declares an object,
any changes to that object will not affect the exception object.
When the handler declares a reference to an object,
any changes to the referenced object are changes to the
exception object and will have effect should that object be rethrown.