# 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) { ... } ```