Exception Handling
Read at your own pace. Code execution, quizzes, progress tracking, and the AI tutor are available in the interactive view with JavaScript enabled.
Errors Need Paths
When programs leave the happy path
In File Handling and I/O operations, you checked whether a file opened successfully before reading it. That was your first serious encounter with runtime failure: the code may be correct, but the world may not cooperate.
Exception handling gives C++ a structured way to handle those runtime problems.
Think of it like this:
- Normal code handles the expected path.
- Exceptions handle unusual but possible failures.
-
try,throw, andcatchcreate a separate error path without burying every line inifchecks.
This matters in real systems: finance apps reject invalid trades, AI pipelines fail on missing model files, and backend services receive malformed requests.

Try Throw Catch
The exception-handling trio
C++ exception handling centers on three keywords:
-
try: marks code where something may go wrong. -
throw: signals that an error occurred. -
catch: handles the thrown error.
A useful mental model:
try block
|
| normal execution
v
continues normally
OR
try block
|
| throw error
v
matching catch block
When C++ sees throw, it stops the current path and searches for a matching catch block.
```cpp
#include <iostream>
#include <stdexcept>
int divide(int numerator, int denominator) {
if (denominator == 0) {
throw std::runtime_error("Cannot divide by zero");
}
return numerator / denominator;
}
int main() {
try {
std::cout << "Result: " << divide(10, 0) << "\n";
std::cout << "This line will not run if an exception is thrown.\n";
} catch (const std::runtime_error& error) {
std::cout << "Caught error: " << error.what() << "\n";
}
std::cout << "Program recovered and kept running.\n";
return 0;
}
```
What Happens Next
A function inside a try block executes throw std::runtime_error("bad input").
What does C++ do next?
Catching Specific Errors
Catch by type
A catch block matches exceptions by type. This lets you respond differently to different kinds of failures.
Common standard exception types include:
-
std::runtime_error: something failed while the program was running. -
std::invalid_argument: a function received an unacceptable argument. -
std::out_of_range: a value tried to access something outside a valid range.
Prefer catching exceptions by const reference:
catch (const std::runtime_error& error)
That avoids unnecessary copying and preserves the exception object's real type.
Ordering matters: put more specific catches before more general ones.

Choose The Handler
Fill in the blank with the C++ keyword that signals an exception:
_____ std::runtime_error("Missing price data");
Multiple Catch Blocks
Different problems, different responses
In web development, you might handle a missing route differently from invalid JSON. C++ has a similar idea: use multiple catch blocks when different failures deserve different responses.
In this example, invalid finance-style input is treated differently from a broader runtime failure.
```cpp
#include <iostream>
#include <stdexcept>
#include <string>
int parseShares(int shares) {
if (shares <= 0) {
throw std::invalid_argument("Share count must be positive");
}
if (shares > 1000000) {
throw std::runtime_error("Trade size exceeds risk limit");
}
return shares;
}
int main() {
try {
int shares = parseShares(-50);
std::cout << "Parsed shares: " << shares << "\n";
} catch (const std::invalid_argument& error) {
std::cout << "Input error: " << error.what() << "\n";
} catch (const std::runtime_error& error) {
std::cout << "Runtime error: " << error.what() << "\n";
} catch (const std::exception& error) {
std::cout << "General error: " << error.what() << "\n";
}
return 0;
}
```
Catch Order Matters
True or false?
When using multiple catch blocks, a general catch (const std::exception& error) should usually come before more specific handlers like catch (const std::invalid_argument& error).
Custom Exceptions
When built-in exceptions are not expressive enough
Standard exceptions are often enough. But sometimes your domain has a failure that deserves a clear name.
Examples:
InsufficientFundsErrorModelLoadErrorPermissionDeniedErrorInvalidPortfolioError
A custom exception makes code easier to read because the type itself explains what went wrong.
The common approach is to create a class that inherits from std::exception and overrides what().
```cpp
#include <iostream>
#include <exception>
class InsufficientFundsError : public std::exception {
public:
const char* what() const noexcept override {
return "Insufficient funds for withdrawal";
}
};
void withdraw(double balance, double amount) {
if (amount > balance) {
throw InsufficientFundsError();
}
std::cout << "Withdrawal approved. Remaining balance: "
<< balance - amount << "\n";
}
int main() {
try {
withdraw(100.0, 250.0);
} catch (const InsufficientFundsError& error) {
std::cout << "Transaction rejected: " << error.what() << "\n";
}
std::cout << "Account system still running.\n";
return 0;
}
```
Unwinding The Stack
Exceptions travel upward
An exception does not need to be caught in the same function where it is thrown.
If a function throws and does not catch the exception, C++ returns control to the caller and keeps searching. This process is called stack unwinding.
main()
calls loadConfig()
calls openFile()
throws error
no catch here
catch found here
This connects to the call stack mental model from Functions And Recursion: C++ backs out of active function calls until it finds a matching handler.
If no handler is found, the program terminates.

Exception Habits
Practical rules of thumb
Use exceptions for unusual failure cases, not everyday control flow.
Good uses:
- A file cannot be opened.
- A required configuration value is missing.
- A function receives invalid input that prevents meaningful work.
- A risk check fails before placing a trade.
Avoid using exceptions for:
- Normal loop exits.
- Simple
if/elsedecisions. - Cases where returning a normal value is clearer.
A solid pattern is:
- Detect the failure close to where it happens.
-
throwan exception with a useful type or message. -
catchit at a level that can actually decide what to do.
Next, you will meet the Standard Template Library, where these ideas become even more useful when working with reusable containers and algorithms.
