Exception handling is a powerful feature in C++ that allows a program to deal with unexpected situations, or exceptions, that occur during program execution. It helps in writing robust and error-resilient applications by separating error-handling code from regular logic.
In this article, we’ll explore the fundamentals of exception handling in C++, how it works, and best practices for using it effectively.
What is an Exception?
An exception is an unexpected event or error that occurs during the execution of a program. Examples include:
- Division by zero
- File not found
- Memory allocation failure
- Invalid user input
If not properly handled, these errors can cause a program to terminate unexpectedly.
Basic Syntax of Exception Handling
C++ uses three main keywords for exception handling:
- try — defines a block of code to test for errors.
- throw — signals that an exception has occurred.
- catch — handles the exception.
Example:
#include <iostream>
using namespace std;
int main() {
int a = 10, b = 0;
try {
if (b == 0)
throw "Division by zero error!";
cout << a / b << endl;
}
catch (const char* msg) {
cout << "Caught an exception: " << msg << endl;
}
return 0;
}
Output:
Caught an exception: Division by zero error!
Multiple Catch Blocks
C++ allows multiple catch
blocks to handle different types of exceptions:
try {
// code that might throw different exceptions
}
catch (int e) {
cout << "Integer exception caught: " << e << endl;
}
catch (const char* msg) {
cout << "String exception caught: " << msg << endl;
}
Catching All Exceptions
If you want to catch any type of exception, you can use the ellipsis ...
as a catch-all handler:
try {
// risky code
}
catch (...) {
cout << "An unknown exception occurred!" << endl;
}
Standard Exception Classes
C++ provides a set of standard exception classes in the <exception>
header:
std::exception
(base class)std::runtime_error
std::out_of_range
std::invalid_argument
, etc.
Example:
#include <iostream>
#include <stdexcept>
using namespace std;
int main() {
try {
throw runtime_error("Runtime error occurred!");
}
catch (exception& e) {
cout << "Caught: " << e.what() << endl;
}
return 0;
}
Exception Propagation
If an exception isn’t handled in the current function, it propagates up the call stack to the calling function until a matching catch
block is found.
Best Practices for Exception Handling
- Only use exceptions for exceptional situations, not for regular control flow.
- Always catch exceptions by reference to avoid slicing.
- Prefer using standard exception classes where possible.
- Clean up resources (like closing files or releasing memory) before exceptions propagate — or use RAII (Resource Acquisition Is Initialization) principles.
Conclusion
Exception handling in C++ is a crucial feature for writing reliable and maintainable code. By properly using try
, throw
, and catch
, developers can gracefully handle runtime errors and ensure their applications remain stable under unexpected conditions.