C++ Custom Exception Classes

In C++, custom exception classes provide a way to define specific error types for domain-specific scenarios. While the standard exceptions in the C++ Standard Library, such as std::runtime_error and std::logic_error, cover many general-purpose use cases, custom exceptions enable developers to create more descriptive and context-specific error handling mechanisms.


Creating Custom Exception Classes

To create a custom exception class, you can define a class that inherits from std::exception or its derived classes (e.g., std::runtime_error). Overriding the what() method provides a description of the error.

Basic Syntax for a Custom Exception Class

</>
Copy
#include <exception>
#include <string>

class CustomException : public std::exception {
    std::string message;

public:
    explicit CustomException(const std::string& msg) : message(msg) {}

    const char* what() const noexcept override {
        return message.c_str();
    }
};

Examples of Custom Exception Classes

Example 1: Basic Custom Exception Class

This example demonstrates a simple custom exception class to handle specific errors.

</>
Copy
#include <iostream>
#include <exception>
#include <string>

class InvalidInputException : public std::exception {
    std::string message;

public:
    explicit InvalidInputException(const std::string& msg) : message("Invalid Input: " + msg) {}

    const char* what() const noexcept override {
        return message.c_str();
    }
};

int main() {
    try {
        int input = -1;
        if (input < 0)
            throw InvalidInputException("Negative numbers are not allowed.");
    } catch (const InvalidInputException& e) {
        std::cerr << e.what() << std::endl;
    }
    return 0;
}

Working of this Program:

  1. Include necessary headers:
    • <iostream>: Used for input/output operations.
    • <exception>: Provides the base std::exception class.
    • <string>: Used for the std::string class to handle string operations.
  2. Define a custom exception class:
    • The class InvalidInputException inherits from std::exception.
    • It has a private member variable message to store the custom error message.
    • The constructor takes a std::string parameter, prepends the text "Invalid Input: ", and stores the result in message.
    • The what() function is overridden to return the custom error message. It returns a C-string using message.c_str() and is marked as noexcept to indicate it doesn’t throw exceptions.
  3. Throw the custom exception:
    • The variable input is initialized to -1.
    • An if statement checks if input is less than 0.
    • If the condition is true, an InvalidInputException is thrown with the message "Negative numbers are not allowed.".
  4. Handle the exception:
    • The try block contains the code that may throw an exception.
    • The catch block captures exceptions of type InvalidInputException.
    • The custom error message is displayed using std::cerr and the what() function of the exception.
  5. Output the result:
    • Since input is -1, the if condition is true, and an exception is thrown with the message "Negative numbers are not allowed.".
    • The catch block captures this exception and outputs: "Invalid Input: Negative numbers are not allowed.".

Output:

Invalid Input: Negative numbers are not allowed.

Example 2: Custom Exception with Additional Information

This example demonstrates a custom exception class that includes additional context, such as an error code.

</>
Copy
#include <iostream>
#include <exception>

class FileException : public std::exception {
    std::string filename;
    std::string message;

public:
    FileException(const std::string& file, const std::string& msg)
        : filename(file), message("File Error [" + file + "]: " + msg) {}

    const char* what() const noexcept override {
        return message.c_str();
    }
};

int main() {
    try {
        std::string file = "data.txt";
        bool fileExists = false; // Simulating a missing file
        if (!fileExists)
            throw FileException(file, "File not found.");
    } catch (const FileException& e) {
        std::cerr << e.what() << std::endl;
    }
    return 0;
}

Output:

File Error [data.txt]: File not found.

Advantages of Custom Exception Classes

  • Specificity: Allow precise identification of different error types.
  • Contextual Information: Provide additional details about the error.
  • Extensibility: Integrate seamlessly with existing error-handling frameworks.

Best Practices for Custom Exception Classes

  • Inheritance: Inherit from std::exception or derived classes for better compatibility with existing error-handling mechanisms.
  • Contextual Information: Include relevant data (e.g., error codes, file names) to make debugging easier.
  • Descriptive Messages: Provide clear and meaningful error messages.
  • Noexcept: Ensure the what() method is marked with noexcept to prevent throwing exceptions during exception handling.

Conclusion

Custom exception classes in C++ provide a robust way to define and handle domain-specific errors. By inheriting from std::exception, developers can create meaningful and descriptive exception types that improve code readability and debugging efficiency. Following best practices ensures that custom exceptions integrate seamlessly with standard error-handling mechanisms.