#include <iostream>
#include <exception>
#include <stdexcept> // stdexcept header contains runtime_error
using namespace std;
new
and operator new[]
when they fail to allocate the requested storage space.{
int* myarray= new int[1000000000000];
cout << "Done!";
}
Standard Exception: std::bad_alloc
try
block.catch
keyword immediately after the closing brace of the try
block.try
{
int* myarray= new int[1000000000000];
}
catch (bad_alloc& e)
{
cout << "This is an exception: " << e.what() << '\n';
}
cout << "Done!";
This is an exception: std::bad_alloc Done!
Define a function quotient
that receives two integers entered by the user and divides its first int
parameter by its second int
parameter.
int
parameter's value to type double
.int
parameter's value is promoted to type double
for the calculation.double
values and returns a double
result.For the purpose of this example we treat any attempt to divide by zero as an error.
quotient
tests its second parameter to ensure that it isn't zero before allowing the division to proceed.// DivideByZeroException objects should be thrown by functions
// upon detecting division-by-zero exceptions
class DivideByZeroException : public std::runtime_error {
public:
// constructor specifies default error message
DivideByZeroException() : runtime_error{"attempted to divide by zero"} {}
};
// perform division and throw DivideByZeroException object if divide-by-zero exception occurs
double quotient(int numerator, int denominator) {
// throw DivideByZeroException if trying to divide by zero
if (denominator == 0) {
throw DivideByZeroException{}; // terminate function
}
// return division result
return static_cast<double>(numerator) / denominator;
}
{
int number1 = 1, number2 = 0;
try {
double result = quotient(number1, number2);
cout << "The quotient is: " << result << endl;
}
catch (const DivideByZeroException& divideByZeroException) {
cout << "Exception occurred: " << divideByZeroException.what() << endl;
}
cout << "Done!";
}
Exception occurred: attempted to divide by zero Done!
runtime_error
class defines only a constructor that passes an error-message string to the base-class runtime_error constructor.what
, which returns an exception object's error message.DivideByZeroException
, from the standard exception classes provided by C++.what
to obtain an appropriate error message and also allows you to polymorphically process the exceptions by catching a reference to the base-class type.Catch
Handler¶catch
handler must immediately follow each try
block.try
block, the try
block expires (i.e., terminates immediately).catch
handler that can process the type of exception that occurred.catch
's exception-parameter type until the program finds a match.catch
handler finishes processing by reaching its closing right brace (}), the exception is considered handled and the local variables defined within the catch handler (including the catch parameter) go out of scope.try
block has expired.catch
handler following the try
block.try
block completes its execution successfully (i.e., no exceptions occur in the try block), then the program ignores the catch
handlers and program control continues with the first statement after the last catch following that try block.try
block has no matching catch
handler, or if an exception occurs in a statement that is not in a try block, the function that contains the statement terminates immediately, and the program attempts to locate an enclosing try
block in the calling function.throw;
void throwException() {
// throw exception and catch it immediately
try {
cout << " Function `throwException` throws an exception\n";
throw exception{}; // generate exception
}
catch (const exception&) { // handle exception
cout << " Exception handled in function `throwException`"
<< "\n Function `throwException` rethrows exception";
throw; // rethrow exception for further processing
}
cout << "This should not print\n";
}
{
// throw exception
try {
cout << "Invoke function throwException\n";
throwException();
cout << "This should not print\n";
}
catch (const exception&) { // handle exception
cout << "\n\nException handled in the caller's scope\n";
}
cout << "Program control continues after catch\n";
}
Invoke function throwException Function `throwException` throws an exception Exception handled in function `throwException` Function `throwException` rethrows exception Exception handled in the caller's scope Program control continues after catch
try...catch
block.try
block encloses that statement, an attempt is made to catch
the exception.try
block does not enclose that statement, stack unwinding occurs again.catch
handler ever catches this exception, the program terminates.// function2 invokes throwException
void function2() {
cout << "`throwException` is called inside `function2`" << endl;
throwException(); // stack unwinding occurs, return control to function1
cout << "Done f2";
}
// function1 invokes function2
void function1() {
cout << "`function2` is called inside `function1`" << endl;
function2(); // stack unwinding occurs, return control to main
cout << "Done f1";
}
{
// invoke function1
try {
cout << "`function1` is called" << endl;
function1(); // call function1 which throws runtime_error
}
catch (const exception& error) { // handle runtime error
cout << "\n\nException occurred: " << error.what() << endl;
cout << "Exception handled" << endl;
}
}
`function1` is called `function2` is called inside `function1` `throwException` is called inside `function2` Function `throwException` throws an exception Exception handled in function `throwException` Function `throwException` rethrows exception Exception occurred: std::exception Exception handled
Error handling:
main
executes.