An exception in C++ is a mechanism that allows handling errors or unexpected situations during the execution of a program.
When an exception occurs:
- It can be caught by a
try-catch
block - If it is not caught, it goes up to the function that invoked the one that generated the error
If there is no try-catch block that captures the exception, it goes “up”. If no one handles it, the exception will reach the main function (the normal behavior is that the program ends abruptly).
Exceptions in C++ are thrown using objects, which can be of any type, although it is common to throw objects of specific types. (such as std::runtime_error
or std::logic_error
).
Throwing an exception
In C++, we can throw an exception using the throw
keyword. This allows us to indicate that a specific error has occurred.
#include <stdexcept>
throw std::runtime_error("An error occurred");
In this example, we throw an exception of type std::runtime_error
with an error message.
This message can later be used in the catch
block to identify and handle the error.
Predefined exceptions
In C++, there are several types of predefined exceptions in the standard library that allow handling common errors. Here are some examples:
std::runtime_error
Indicates errors during execution, such as I/O operation failures or unexpected logic issues.
throw std::runtime_error("Runtime error");
std::logic_error
Indicates logic errors in the program, such as incorrect argument conditions.
throw std::logic_error("Logical error in the application");
std::out_of_range
Thrown when trying to access an element outside the valid range, for example, in a vector or array.
#include <vector>
std::vector<int> numbers = {1, 2, 3};
int value = numbers.at(5); // Will throw std::out_of_range
std::overflow_error
Indicates an overflow error in arithmetic calculations.
throw std::overflow_error("Arithmetic overflow");
std::underflow_error
Similar to std::overflow_error
, but indicates a negative or low underflow.
std::invalid_argument
Indicates an invalid argument in a function.
#include <stdexcept>
void setAge(int age) {
if (age < 0) throw std::invalid_argument("Age cannot be negative");
}
setAge(-5); // Will throw std::invalid_argument
std::bad_alloc
Thrown when a memory allocation operation fails.
try {
int* arr = new int[100000000000]; // Attempt to allocate too much memory
} catch (const std::bad_alloc& e) {
std::cout << "Memory allocation error: " << e.what() << std::endl;
}
These are just some of the common exceptions in C++. The standard library includes more specific exceptions for various situations.
Creating custom exceptions in C++
In C++, it is also possible to define custom exceptions by creating classes that inherit from a base exception class, such as std::exception
.
#include <exception>
#include <string>
class MyException : public std::exception {
std::string message;
public:
explicit MyException(const std::string& message) : message(message) {}
const char* what() const noexcept override {
return message.c_str();
}
};
Here, MyException
inherits from std::exception
and overrides the what()
method to provide a custom error message.
Using a custom exception
We can use our custom exception class in a try-catch
block like any other exception:
#include <iostream>
int main() {
try {
throw MyException("Error in my custom application");
} catch (const MyException& e) {
std::cout << "Custom exception caught: " << e.what() << std::endl;
}
return 0;
}
In this case, the error message from MyException
will be printed to the console.