Exception handling is a way to detect and handle runtime errors without terminating the program unexpectedly. It uses the try, throw, and catch keywords to handle exceptions.
- try contains code that may generate an exception.
- throw signals an exception when an error occurs.
- catch handles the exception thrown by the try block.
#include <iostream>
using namespace std;
int main() {
int a = 10, b = 0;
try {
if (b == 0)
throw "Division by zero is not allowed.";
cout << a / b;
}
catch (const char* msg) {
cout << msg;
}
return 0;
}
Output
Division by zero is not allowed.
Explanation
- The try block checks whether the divisor is zero.
- If b is 0, the throw statement sends an error message to the catch block.
Note: Integer division by zero does not automatically generate a C++ exception. The error must be handled explicitly, as shown above.
Methods of Handling Exceptions
C++ provides different ways to handle exceptions depending on the type and source of the error.
Handling a Single Exception
A single catch block can be used when the program needs to handle one specific type of exception.
#include <iostream>
using namespace std;
int main() {
try {
throw 10;
}
catch (int x) {
cout << "Exception: " << x;
}
return 0;
}
Output
Exception: 10
Handling Multiple Exception Types
Multiple catch blocks can be used to handle different types of exceptions. Each catch block handles a specific exception type.
#include <iostream>
using namespace std;
int main() {
try {
throw 3.14;
}
catch (int x) {
cout << "Integer exception: " << x;
}
catch (double x) {
cout << "Double exception: " << x;
}
return 0;
}
Output
Double exception: 3.14
Handling All Exception Types
A catch-all handler can be used to handle exceptions of any type. The catch (...) block catches any exception that is not handled by a more specific catch block.
#include <iostream>
using namespace std;
int main() {
try {
throw "Unknown error";
}
catch (...) {
cout << "An exception occurred.";
}
return 0;
}
Output
An exception occurred.
C++ Standard Exceptions
C++ defines a set of standard exceptions defined in <exception> which can be used in the programs. These exceptions are arranged in the parent-child class hierarchy. Below is the table listing the standard exceptions with description:
| Exception | Description |
|---|---|
| std::exception | Base class for many standard exceptions. |
| std::bad_alloc | Indicates that memory allocation failed. |
| std::bad_cast | Thrown when a reference dynamic_cast fails. |
| std::bad_typeid | Thrown when typeid is used incorrectly with a null polymorphic pointer. |
| std::logic_error | Base class for errors caused by incorrect program logic. |
| std::invalid_argument | Indicates an invalid argument was passed to a function. |
| std::out_of_range | Indicates that an operation tried to access an element outside a valid range. |
| std::length_error | Indicates that an operation exceeds the maximum allowed size. |
| std::runtime_error | Base class for errors that can occur during program execution. |
Handling std::out_of_range
The at() function of vector throws std::out_of_range when the requested index is outside the valid range.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> numbers = {10, 20, 30};
try {
cout << numbers.at(5);
}
catch (const out_of_range& e) {
cout << "Exception: " << e.what();
}
return 0;
}
Output
Exception: vector::_M_range_check: __n (which is 5) >= this->size() (which is 3)
Explanation
- numbers.at(5) tries to access an index that does not exist.
- std::out_of_range is caught and what() returns a description of the error.
Catching Exceptions Using std::exception
Since many standard exceptions derive from std::exception, a single catch block can handle them.
#include <iostream>
#include <vector>
#include <exception>
using namespace std;
int main() {
vector<int> numbers = {10, 20, 30};
try {
cout << numbers.at(5);
}
catch (const exception& e) {
cout << "Exception: " << e.what();
}
return 0;
}
Output
Exception: vector::_M_range_check: __n (which is 5) >= this->size() (which is 3)
The std::exception reference can catch many types of standard exceptions and what() provides an error description.
Creating Custom Exceptions
C++ also allows programmers to create their own exception classes for application-specific errors.
#include <iostream>
#include <exception>
using namespace std;
class InvalidAge : public exception {
public:
const char* what() const noexcept override {
return "Age cannot be negative.";
}
};
int main() {
try {
int age = -10;
if (age < 0)
throw InvalidAge();
cout << "Valid age";
}
catch (const InvalidAge& e) {
cout << e.what();
}
return 0;
}
Output
Age cannot be negative.
Explanation
- InvalidAge is a custom exception class derived from std::exception.
- The what() function provides a description of the error.