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_error
std::invalid_argument
std::out_of_range
std::overflow_error
std::underflow_error
std::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.