Exception Handling using Classes in C++

Last Updated : 4 Jul, 2026

Exception handling in C++ allows programs to handle runtime errors gracefully using objects called exceptions. Instead of abruptly terminating the program, exceptions can be thrown and caught using try, throw, and catch blocks.

  • Exception objects provide detailed information about errors.
  • C++ supports both standard exception classes and user-defined exception classes.

Standard Exception Classes

C++ provides several built-in exception classes for representing common runtime errors. Most standard exceptions are derived from the std::exception class.

std::exception Base Class

C++
class exception {
public:

    exception() noexcept;
    exception(const exception&) noexcept;
    exception& operator=(const exception&) noexcept;
    
    virtual ~exception();
    virtual const char* what() const noexcept;
};

The what() function returns a description of the exception. Since it is a virtual function, derived exception classes can provide their own error messages.

Common Standard Exception Classes

Exception ClassDescription
invalid_argumentInvalid arguments passed to a function
out_of_rangeAccess outside valid range
domain_errorMathematical domain errors
runtime_errorRuntime errors
overflow_errorArithmetic overflow
underflow_errorArithmetic underflow
ios_base::failureInput/output operation failures
bad_castFailed dynamic_cast operation
bad_allocMemory allocation failure

These exceptions are commonly thrown by C++ library components and should be handled appropriately.

Example: Handling a Standard Exception

C++
#include <bits/stdc++.h>
using namespace std;

int main() {
    try {
        
        // Try allocating a huge block of memory
        int* bigArray = new int[100000000000000];  
        
    } catch (const bad_alloc& e) {
        cout << "Caught bad_alloc: " << e.what();
    }
    
    // Moving on to next part of the code

    return 0;
}

Output
Caught bad_alloc: std::bad_alloc

Explanation: The memory allocation fails and throws a std::bad_alloc exception, which is caught and handled using the catch block.

Throwing Standard Exception Objects

Programmers can also manually throw standard exception objects.

C++
#include <bits/stdc++.h>
using namespace std;

int main() {
    int num = 10;
    int den = 0;
	int res;
	
	// Checking division by zero
    try {
        if (!den) {
            
            // Passing custom message
            throw runtime_error("Division by Zero");
        }
		res = num/den;
    }
	catch (const runtime_error& e) {
        cout << "Caught: " << e.what();
    }

    return 0;
}

Output
Caught: Division by Zero

Explanation: A runtime_error object is explicitly thrown with a custom error message and later handled in the corresponding catch block.

Creating Custom Exception Classes

When standard exception classes are insufficient, programmers can create their own exception classes.

There are mainly three ways to create custom exception classes in C++:

Deriving from std::exception

The simplest and most common approach is to inherit from std::exception and override the what() function.

C++
#include <bits/stdc++.h>
using namespace std;

// Create an own custom class for
// exception handling
class CustomExcept : public exception {
public:
    
    // Override what() function
    const char* what() const noexcept override {
        return "This is a custom exception!";
    }
};

int main() {
    try {
        
        // Throwing our custom exception
        throw CustomExcept();  
    }
    catch (const CustomExcept& e) {
        cout << "Caught an exception: " << e.what();  
    }
    return 0;
}

Output
Caught an exception: This is a custom exception!

Explanation: The custom exception class overrides what() to provide its own error message.

Deriving from Other Standard Exceptions

Custom exceptions can also inherit from classes such as runtime_error or logic_error.

C++
#include <bits/stdc++.h>
using namespace std;

class CustomExcept : public runtime_error {
public:

	// Using constructor for passing custom message
	CustomExcept(const string& message)
        : runtime_error(message) {}
};

int main() {
    try {
        throw CustomExcept(
            "This is a custom runtime_exception!"
        );
    }
    catch (const CustomExcept& e) {
        cout << e.what();
    }
    return 0;
}

Output
This is a custom runtime_exception!

Explanation: The custom exception inherits the functionality of runtime_error, including support for custom messages.

Creating a Non-Standard Exception Class

A custom exception class can also be created without inheriting from any standard exception class.

C++
#include <bits/stdc++.h>
using namespace std;

class CustomExcept {
public:
	CustomExcept(const string& msg) : message(msg) {}
    
    // Handle custom exception using
    // what() method.
    const char* what() const {
        return message.c_str();
    }

private:
    string message;
};

int main() {
    try {
        throw CustomExcept(
            "This is a custom exception!"
        );
    }
    catch (const CustomExcept& e) {
        cout << e.what();
    }
    return 0;
}

Output
This is a custom exception!

Explanation: The exception class stores and returns its own error message without relying on the standard exception hierarchy.

Best Practices

The following practices help create effective exception classes in C++:

  • Prefer deriving custom exceptions from std::exception.
  • Override the what() function to provide meaningful error messages.
  • Catch exceptions using const references.
  • Use standard exception classes whenever possible.
Comment