In real-world software, things can go wrong: a file might not open, a network might fail, or an invalid value might sneak into your program. Exception handling is a key feature in C++ that allows you to gracefully manage such errors without crashing the entire program.
In this guide, you’ll learn:
- What exception handling is
- How to use
try,catch, andthrow - What types of exceptions exist
- Best practices for writing clean, maintainable error-handling code
What is Exception Handling?
Exception handling in C++ is a mechanism to handle runtime errors — errors that occur while the program is running, not during compilation.
Rather than using return codes or flags, C++ lets you “throw” exceptions when something goes wrong, and “catch” them where you can respond appropriately.
Basic Syntax
try {
// Code that may throw an exception
} catch (exception_type variable) {
// Code that handles the exception
}
Example:
#include <iostream>
using namespace std;
int divide(int a, int b) {
if (b == 0)
throw "Division by zero!";
return a / b;
}
int main() {
try {
int result = divide(10, 0);
cout << "Result: " << result << endl;
} catch (const char* msg) {
cout << "Error: " << msg << endl;
}
return 0;
}
Output:
Error: Division by zero!
The throw Keyword
You use throw to signal that an exception has occurred.
throw value; // value can be an int, string, object, etc.
Examples:
throw -1; // throws an int
throw "Invalid input"; // throws a C-string
throw std::runtime_error("File not found"); // throws a standard exception object
The try Block
Put all code that might throw an exception inside a try block.
try {
risky_function();
}
The catch Block
catch handles the error. You can have multiple catch blocks for different exception types.
catch (int e) {
// Handle int exceptions
}
catch (const char* msg) {
// Handle C-string exceptions
}
catch (...) {
// Catch-all handler for any exception type
}
Example with Multiple Catch Blocks
try {
throw 3.14;
} catch (int e) {
cout << "Caught int: " << e << endl;
} catch (double e) {
cout << "Caught double: " << e << endl;
} catch (...) {
cout << "Caught unknown exception." << endl;
}
Output:
Caught double: 3.14
Standard Exceptions in C++
C++ provides a set of predefined exception classes in the <stdexcept> header.
Common ones:
std::runtime_errorstd::invalid_argumentstd::out_of_rangestd::overflow_errorstd::underflow_errorstd::logic_error
Example:
#include <iostream>
#include <stdexcept>
using namespace std;
int main() {
try {
throw std::out_of_range("Index out of range!");
} catch (const std::exception& e) {
cout << "Caught exception: " << e.what() << endl;
}
return 0;
}
Custom Exception Classes
You can define your own exception class by inheriting from std::exception.
class MyException : public std::exception {
public:
const char* what() const noexcept override {
return "Custom exception occurred!";
}
};
Use it like this:throw MyException();
Nested Try-Catch Blocks
You can also use try-catch inside other try-catch blocks:
try {
try {
throw 100;
} catch (int x) {
cout << "Inner catch: " << x << endl;
throw; // rethrow
}
} catch (...) {
cout << "Outer catch." << endl;
}
Best Practices
- Throw exceptions, don’t return error codes
- Use standard exceptions where possible
- Catch exceptions by reference, especially for objects
- Avoid exception handling in performance-critical code, if not needed
- Use RAII (Resource Acquisition Is Initialization) to avoid memory leaks on exceptions
- Never throw exceptions from destructors
Final Thoughts
Exception handling in C++ allows you to write safer, more robust applications by properly managing unexpected runtime errors. It’s essential in real-world development where external inputs, resources, and logic can often go wrong.
Understanding how to use try, catch, and throw — along with proper exception design — is a fundamental part of writing professional-grade C++ code.
