# C++ Exception Handling
## What's try/catch in C++
try and catch are used for exception handling — a way to handle errors or unexpected events without crashing the program.
- try block: You write code that might throw an exception.
- catch block: You write code that handles the exception if one is thrown.
## Syntax
```c++
try {
// Code that might throw an exception
} catch (ExceptionType e) {
// Code to handle the exception
}
```
## Example
```c++
#include <iostream>
using namespace std;
int main() {
int a = 10, b = 0;
try {
if (b == 0)
throw runtime_error("Division by zero!");
cout << "Result: " << a / b << endl;
} catch (runtime_error &e) {
cout << "Caught an exception: " << e.what() << endl;
}
return 0;
}
```
## Create own exception class
```c++
#include <exception>
// compatible with c++98
class GradeTooHighException : public std::exception {
public:
const char* what() const throw() {
return "Grade is too high!";
}
};
```
1. Inherit from ```std::exception```
- std::exception: base class for all standard exceptions
2. Override ```what()```
- what(): return a C-style string describing the error
- virtual:
## Key concept
| Concept | Meaning |
| ---------- | ------------------------------------------------------------------- |
| `throw` | Used to raise an exception |
| `try` | Code block where an exception may be thrown |
| `catch` | Code block that handles a specific type of exception |
| `e.what()` | Returns a string describing the exception (for standard exceptions) |
- Always catch exceptions by reference (eg. ```catch (const std::exception &e)```) to avoid slicing and copying.
- You can have multiple ```catch``` blocks for different types.
- There’s also a catch-all syntax: ```catch (...) {}``` for unknown exceptions.
## When to use
- You're working with risky operations (e.g., file I/O, network, user input, division, dynamic memory).
- You want to gracefully handle errors and continue the program.
## Notes
**Catch by value would call copy constructor, which might be**
- slow (perf cost)
- dangerous (object slicing or unintended behaviour)
- impossible (some exception types are not copyable)
**What's object slicing?**
- Happen when a derived class object is assigned or copied into a base class by value, causing the derived-specific parts to be sliced off
- Analogy
- Imagine Base is a box, and Derived is a bigger box with extra compartments.
- If you copy a Derived box into a Base box, you only keep the smaller part — the extra compartments are sliced off.
- Example of slicing in exceptions
```c++
class MyError : public std::runtime_error {
public:
MyError() : std::runtime_error("my error") {}
void customStuff() const { cout << "MyError specific" << endl; }
};
try {
throw MyError();
} catch (std::runtime_error e) { // ❌ Caught by value: slicing occurs
cout << e.what() << endl;
// e.customStuff(); ❌ not accessible, sliced away
}
```
✅ Instead, catch by reference to avoid slicing:
```c++
catch (const std::runtime_error &e) { ... }
```