Exception
Exception Handling
When executing a program, error occurs. It's important to handle the error properly. In C++, exception is the idiomatic way to handle error.
// `try` tries to execute the block of code
// and hands over to `catch` if an exception is thrown
try {
int numerator = 10;
int denominator = 0;
int result = numerator / denominator; // Potential division by zero
// This line won't be executed if an exception is thrown above
std::cout << "Result: " << result << std::endl;
} catch (const std::exception& e) {
// handle the exception
std::cout << "An exception occurred: " << e.what() << std::endl;
}
// `catch` can be chained to handle specific exceptions
try {
std::string s = "hello";
s[10] = 'x'; // Accessing an invalid index throws an out_of_range exception
} catch (const std::out_of_range& e) {
std::cout << "Out of range exception: " << e.what() << std::endl;
} catch (const std::exception& e) {
std::cout << "An exception occurred: " << e.what() << std::endl;
} catch (...) {
std::cout << "An unknown exception occurred." << std::endl;
}
// `throw` can be used to throw an exception manually
void func() {
// when exception is thrown, the control is transferred to the nearest `catch` block
throw std::runtime_error("An error occurred in func()");
// unreachable code
std::cout << "This line won't be executed" << std::endl;
}
try {
func();
} catch (const std::exception& e) {
std::cout << "An exception occurred: " << e.what() << std::endl;
}
noexcept
Guarantee
The noexcept
keyword is used to declare that a function does not throw any
exceptions. If a function marked with noexcept
does throw an exception, the
std::terminate
function is called, terminating the program.
// won't fail guarantee
void func() noexcept { /* ... */ }
// specialized won't fail
template <> void func<int>() noexcept { /* ... */ }
template <> void func() noexcept(sizeof(T) == 4) { /* ... */ }
Custom Exception
We can define custom exception by inheriting from std::exception
.
#include <stdexcept>
class MyException : public exception {
private:
std::string m_message;
public:
MyException(const std::string& msg) : m_message(msg) {}
std::string what() override { return m_message; }
};
try {
throw MyException("An error occurred in func()");
} catch (const std::exception& e) {
std::cout << "An exception occurred: " << e.what() << std::endl;
}
// specialized exception
#include <stdexcept>
class RunOutOfMemory : public std::runtime_error {
public:
RunOutOfMemory(const std::string& msg) : std::runtime_error(msg) {}
};