C++ Exception Handling: try/catch/throw, std::exception & Stack Unwinding

Exception Handling provides a structured mechanism to detect, transmit, and resolve unexpected runtime errors (such as network loss, missing files, or out-of-memory errors) without abruptly crashing the application.

C++ Standard Exception Class Hierarchy Diagram
Figure 17: The Standard C++ Exception Class Hierarchy (std::exception)

Custom Exception Class Implementation

#include <iostream>
#include <stdexcept>
#include <string>

// Custom domain exception deriving from std::runtime_error
class InsufficientFundsException : public std::runtime_error {
public:
    explicit InsufficientFundsException(double deficit)
        : std::runtime_error("Withdrawal rejected: Shortfall of $" + std::to_string(deficit)) {}
};

class BankAccount {
private:
    double balance;
public:
    BankAccount(double b) : balance(b) {}

    void withdraw(double amount) {
        if (amount > balance) {
            throw InsufficientFundsException(amount - balance); // Throw custom exception
        }
        balance -= amount;
        std::cout << "Withdrawal successful. Remaining: $" << balance << "\n";
    }
};

int main() {
    BankAccount account(500.0);

    try {
        account.withdraw(200.0);
        account.withdraw(450.0); // Throws InsufficientFundsException!
    } catch (const InsufficientFundsException& e) {
        std::cerr << "[ACCOUNT ERROR]: " << e.what() << "\n";
    } catch (const std::exception& e) {
        std::cerr << "[STANDARD ERROR]: " << e.what() << "\n";
    }

    return 0;
}

Frequently Asked Questions (FAQ) - Student & Interview Review

Q1. Why should you always catch exceptions by const reference (catch (const std::exception& e))?

Catching by value causes Object Slicing (derived exception data is stripped away) and copies the exception object. Catching by pointer requires manual deletion. Catching by 'const reference' preserves full polymorphism and avoids copying.

Q2. What does the 'noexcept' keyword do in C++11?

The 'noexcept' specifier guarantees that a function will never throw an exception. If an exception escapes a noexcept function, std::terminate() is called immediately. Marking move constructors noexcept enables STL containers like vector to use move operations during reallocation.

Explore Related C++ Tutorials & Next Steps

Boost your C++ proficiency by studying these closely connected core modules:

C++ RAII

How RAII prevents leaks during stack unwinding.

File Streams

Handling I/O stream exceptions.

Multithreading

Exception safety across thread boundaries.

Share Share on Facebook Share on Twitter Share on LinkedIn Pin on Pinterest Share on Stumbleupon Share on Tumblr Share on Reddit Share on Diggit

You may also like this!