Fundamentals 8 min read

Why and How to Create Custom Exceptions in C++ for Robust Error Handling

This article explains why custom exceptions are essential for clear, domain‑specific error reporting in C++, shows step‑by‑step how to define them by inheriting from standard exception classes, provides practical code examples, and outlines best practices for designing maintainable exception hierarchies.

php Courses
php Courses
php Courses
Why and How to Create Custom Exceptions in C++ for Robust Error Handling

In earlier sections we learned about standard C++ exception types such as std::runtime_error and std::out_of_range. However, in complex projects the standard exceptions often lack the precision needed to describe specific errors, making custom exceptions a key technique for building robust, maintainable, and debuggable C++ applications.

Why need custom exceptions?

Express domain‑specific errors, e.g., an InsufficientFundsException in a banking app conveys the problem more clearly than a generic std::runtime_error("Withdrawal amount too large").

Carry rich error information: custom exception classes can hold additional members such as error codes, operation IDs, timestamps, etc.

Fine‑grained catch blocks: a catch clause can target a specific exception type to execute precise recovery logic.

Improve code readability and maintainability: the exception class name acts as documentation of possible problems.

How to create a custom exception class?

In C++, creating a custom exception class is straightforward: define a new class that publicly inherits from a standard exception class (usually std::exception or one of its derivatives).

Basic steps:

Include necessary headers:

#include <exception> // for std::exception
#include <string>    // for std::string

Derive from std::exception (or a derived class such as std::runtime_error ). Inheriting from std::runtime_error is often preferable because it already stores a string message.

Override the what() method. The base class defines the virtual function virtual const char* what() const noexcept; , which must be overridden to return your custom error message.

Example 1: Inherit from std::exception

#include <exception>
#include <string>

class MyCustomException : public std::exception {
private:
    std::string message; // stores detailed error information
public:
    explicit MyCustomException(const std::string& msg) : message(msg) {}
    const char* what() const noexcept override { return message.c_str(); }
};

Usage example:

#include <iostream>

void riskyFunction(int value) {
    if (value < 0) {
        throw MyCustomException("Input value cannot be negative!");
    }
    // ... normal logic
}

int main() {
    try {
        riskyFunction(-5);
    } catch (const MyCustomException& e) {
        std::cerr << "Caught my custom exception: " << e.what() << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Caught standard exception: " << e.what() << std::endl;
    }
    return 0;
}
// Output: Caught my custom exception: Input value cannot be negative!

Example 2: Preferred way — inherit from std::runtime_error

The std::runtime_error class already maintains a string message and overrides what(), so inheriting from it makes the code more concise.

#include <stdexcept>

class FileOpenException : public std::runtime_error {
public:
    explicit FileOpenException(const std::string& filename)
        : std::runtime_error("Failed to open file: " + filename) {}
};

Usage example:

#include <fstream>

void openFile(const std::string& filename) {
    std::ifstream file(filename);
    if (!file.is_open()) {
        throw FileOpenException(filename);
    }
    // ... file operations
}

int main() {
    try {
        openFile("nonexistent.txt");
    } catch (const FileOpenException& e) {
        std::cerr << e.what() << std::endl; // Output: Failed to open file: nonexistent.txt
    }
    return 0;
}

Create more complex custom exceptions

class DatabaseQueryException : public std::runtime_error {
private:
    int errorCode;
    std::string failedQuery;
public:
    DatabaseQueryException(int code, const std::string& query, const std::string& message)
        : std::runtime_error(message), errorCode(code), failedQuery(query) {}
    int getErrorCode() const { return errorCode; }
    const std::string& getFailedQuery() const { return failedQuery; }
};

// Usage
try {
    // ... execute DB query
    throw DatabaseQueryException(1064, "SELECT * FROM non_existent_table", "Syntax error in SQL query");
} catch (const DatabaseQueryException& e) {
    std::cerr << "DB Error (" << e.getErrorCode() << "): " << e.what() << "
";
    std::cerr << "Failed query: " << e.getFailedQuery() << std::endl;
}
// Output:
// DB Error (1064): Syntax error in SQL query
// Failed query: SELECT * FROM non_existent_table

Best practices

Prefer inheriting from std::runtime_error to avoid managing string messages yourself.

Catch exceptions by const reference to avoid slicing and unnecessary copies.

Keep the noexcept guarantee when overriding what() because it should not throw.

Design a clear exception hierarchy: create a base class derived from std::exception and let specific exceptions inherit from it.

Provide meaningful error information with sufficient context to locate problems quickly.

Summary

Custom exceptions are a powerful and flexible feature of C++'s exception handling mechanism. By deriving from standard exception classes, you can create semantically clear, information‑rich, and targeted error types that greatly improve code quality and debuggability; a well‑designed exception class serves as excellent documentation.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Cbest practicescustom-exceptionruntime_errorexception hierarchy
php Courses
Written by

php Courses

php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.