To catch exceptions, a portion of code is placed under exception inspection. This is done by enclosing that portion of code in a try-block. When an exceptional circumstance arises within that block, an exception is thrown that transfers the control to the exception handler. If no exception is thrown, the code continues normally and all handlers are ignored.
An exception is thrown by using the throw
keyword from inside the try
block. Exception handlers are declared with the keyword catch
, which must be placed immediately after the try
block:
// exceptions
#include <iostream>
using namespace std;
int main () {
try
{
throw 20;
}
catch (int e)
{
cout << "An exception occurred. Exception Nr. " << e << '\n';
}
return 0;
}
An exception occurred. Exception Nr. 20
try
block. In this example this code simply throws an exception:
throw
expression accepts one parameter (in this case the integer value 20
), which is passed as an argument to the exception handler.
The exception handler is declared with the catch
keyword immediately after the closing brace of the try
block. The syntax for catch
is similar to a regular function with one parameter. The type of this parameter is very important, since the type of the argument passed by the throw
expression is checked against it, and only in the case they match, the exception is caught by that handler.
Multiple handlers (i.e., catch
expressions) can be chained; each one with a different parameter type. Only the handler whose argument type matches the type of the exception specified in the throw
statement is executed.
If an ellipsis (...
) is used as the parameter of catch
, that handler will catch any exception no matter what the type of the exception thrown. This can be used as a default handler that catches all exceptions not caught by other handlers:
1
2
3
4
5
6
try {
// code here
}
catch (int param) { cout << "int exception"; }
catch (char param) { cout << "char exception"; }
catch (...) { cout << "default exception"; }
int
nor char
.
After an exception has been handled the program, execution resumes after the try-catch block, not after the throw
statement!.
It is also possible to nest try-catch
blocks within more external try
blocks. In these cases, we have the possibility that an internal catch
block forwards the exception to its external level. This is done with the expression throw;
with no arguments. For example:
1
2
3
4
5
6
7
8
9
10
11
try {
try {
// code here
}
catch (int n) {
throw;
}
}
catch (...) {
cout << "Exception occurred";
}
throw
specifier to it. For example:
1
double myfunction (char param) throw (int);
myfunction
, which takes one argument of type char
and returns a value of type double
. If this function throws an exception of some type other than int
, the function calls std::unexpected instead of looking for a handler or calling std::terminate.
If this throw
specifier is left empty with no type, this means that std::unexpected is called for any exception. Functions with no throw
specifier (regular functions) never call std::unexpected, but follow the normal path of looking for their exception handler.
1
2
int myfunction (int param) throw(); // all exceptions call unexpected
int myfunction (int param); // normal exception handling
std::exception
and is defined in the <exception>
header. This class has a virtual member function called what
that returns a null-terminated character sequence (of type char *
) and that can be overwritten in derived classes to contain some sort of description of the exception.
// using standard exceptions
#include <iostream>
#include <exception>
using namespace std;
class myexception: public exception
{
virtual const char* what() const throw()
{
return "My exception happened";
}
} myex;
int main () {
try
{
throw myex;
}
catch (exception& e)
{
cout << e.what() << '\n';
}
return 0;
}
My exception happened.
&
after the type), therefore this catches also classes derived from exception
, like our myex
object of type myexception
.
All exceptions thrown by components of the C++ Standard library throw exceptions derived from this exception
class. These are:
exception
, header <exception>
defines two generic exception types that can be inherited by custom exceptions to report errors:
exception description logic_error
error related to the internal logic of the program runtime_error
error detected during runtime
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// bad_alloc standard exception
#include <iostream>
#include <exception>
using namespace std;
int main () {
try
{
int* myarray= new int[1000];
}
catch (exception& e)
{
cout << "Standard exception: " << e.what() << endl;
}
return 0;
}
bad_alloc
. Because bad_alloc
is derived from the standard base class exception
, it can be caught (capturing by reference, captures all related classes).
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4