Topic 68 of 91 9. C++ Standard Template Library (STL) Interactive Tutorial

Custom Exceptions in C++: Creating Application-Specific Error Types

7 mins read Last updated: 26 Sep 2026 17,316 views

Direct Answer & Core Concept

Custom exceptions are created by deriving from std::exception, std::runtime_error, or std::logic_error and overriding the virtual const char* what() const noexcept method (or passing an error message to the std::runtime_error base constructor). This provides descriptive, domain-specific error reporting.

Detailed Explanation & Mechanics

1. Designing Custom Exception Classes:

Inheriting from std::runtime_error is the most common approach because it handles string storage internally:

Architecture Diagram
CUSTOM EXCEPTION HIERARCHY:
       ┌────────────────────────┐
       │   std::runtime_error   │
       └───────────┬────────────┘
                   │
       ┌───────────┴────────────┐
       │   NetworkTimeoutError  │ ──► provides errorCode + what()
       └────────────────────────┘

2. Overriding `what()`:

const char* what() const noexcept override must be marked noexcept to match the standard signature.

Runnable Code Example: Custom Exceptions in C++

C++20 / C++23
main.cpp
Run Online
#include <iostream>
#include <string>
#include <stdexcept>

// Custom Exception inheriting from std::runtime_error
class InsufficientFundsException : public std::runtime_error {
private:
    double currentBalance;
    double requestedAmount;

public:
    InsufficientFundsException(double balance, double requested)
        : std::runtime_error("Insufficient funds for requested transaction."),
          currentBalance(balance),
          requestedAmount(requested) {}

    double getBalance() const noexcept { return currentBalance; }
    double getRequested() const noexcept { return requestedAmount; }
};

void withdraw(double& balance, double amount) {
    if (amount > balance) {
        throw InsufficientFundsException(balance, amount);
    }
    balance -= amount;
    std::cout << "Withdrew $" << amount << ". New balance: $" << balance << "\n";
}

int main() {
    double accountBalance = 250.00;

    try {
        withdraw(accountBalance, 100.00);
        withdraw(accountBalance, 500.00); // Exceeds balance
    }
    catch (const InsufficientFundsException& ex) {
        std::cerr << "[Exception Caught]: " << ex.what() << "\n"
                  << "  Balance: $" << ex.getBalance() << "\n"
                  << "  Attempted: $" << ex.getRequested() << "\n";
    }
    return 0;
}

Common C++ Technical Interview Questions & Answers

Interview Prep
Q

Q: Why inherit from `std::runtime_error` rather than raw `std::exception`?

A: `std::runtime_error` already encapsulates an `std::string` message and implements `.what()`, reducing boilerplate code in your custom exception.
Q

Q: Why must `what()` be declared `noexcept`?

A: In `std::exception`, `what()` is defined as `virtual const char* what() const noexcept;`. In C++, an overriding method cannot have a looser exception specification than the base method.

Key Takeaways, Modern Best Practices & Idioms

C++ Best Practices & Production Rules

• Derive custom exceptions from std::runtime_error (for runtime failures) or std::logic_error (for logic/invariant bugs).
• Include helpful contextual telemetry (error codes, usernames, transaction IDs) in custom exception classes.
• Catch custom exceptions before generic base exceptions in try-catch chains to ensure specific handling.
We value your privacy & transparency

OperateTools uses cookies and local storage to ensure basic tool functionality, preserve preferences, and analyze aggregated traffic. We never sell your personal data or index your document files. Learn more in our Privacy Policy.