User-defined Custom Exception with class in C++

Last Updated : 17 Jan, 2026

In C++, exceptions are not limited to built-in data types. We can also define our own exception types using classes and throw objects of those classes. This allows developers to represent application-specific error conditions in a structured and type-safe way.

A user-defined exception is thrown using:

throw ClassName();

Example 1: Exception Handling with a Single Class

CPP14
#include <iostream>
using namespace std;

class demo {
};

int main() {
    try {
        throw demo();
    }
    catch (demo d) {
        cout << "Caught exception of demo class\n";
    }
}

Output
Caught exception of demo class

Explanation:

  • demo is an empty user-defined class.
  • An object of demo is thrown using throw demo().
  • The corresponding catch block catches the exception based on its type.
  • The exception is handled successfully without program termination.

Example 2: Exception Handling with Multiple Classes

CPP14
#include <iostream>
using namespace std;

class demo1 {
};

class demo2 {
};

int main() {
    for (int i = 1; i <= 2; i++) {
        try {
            if (i == 1)
                throw demo1();
            else
                throw demo2();
        }
        catch (demo1 d1) {
            cout << "Caught exception of demo1 class\n";
        }
        catch (demo2 d2) {
            cout << "Caught exception of demo2 class\n";
        }
    }
}

Output
Caught exception of demo1 class
Caught exception of demo2 class

Exception handling with inheritance

When exception classes are related through inheritance, the order of catch blocks becomes important. 

CPP14
#include <iostream>
using namespace std;

class demo1 {
};

class demo2 : public demo1 {
};

int main() {
    for (int i = 1; i <= 2; i++) {
        try {
            if (i == 1)
                throw demo1();
            else
                throw demo2();
        }
        catch (demo1 d1) {
            cout << "Caught exception of demo1 class\n";
        }
        catch (demo2 d2) {
            cout << "Caught exception of demo2 class\n";
        }
    }
}

Output
Caught exception of demo1 class
Caught exception of demo1 class

Explanation:

  • demo2 is derived from demo1.
  • The catch (demo1) block appears before catch (demo2).
  • Since base-class handlers match derived objects, the demo2 exception is caught by demo1.
  • Best practice: Always place derived-class catch blocks before base-class handlers.

Exception handling with constructor

Exceptions can also be thrown and handled inside constructors.

CPP14
#include <iostream>
using namespace std;

class demo {
    int num;

public:
    demo(int x) {
        try {
            if (x == 0)
                throw "Zero not allowed";

            num = x;
            show();
        }
        catch (const char* exp) {
            cout << "Exception caught\n";
            cout << exp << endl;
        }
    }

    void show() {
        cout << "Num = " << num << endl;
    }
};

int main() {
    demo(0);
    cout << "Again creating object\n";
    demo(1);
}

Output
Exception caught
Zero not allowed
Again creating object
Num = 1

Explanation:

  • The constructor validates input before initializing the object.
  • When x == 0, an exception is thrown and caught inside the constructor.
  • Object creation continues normally for valid input (x = 1).
  • Constructors cannot return values, but exceptions allow error signaling during object creation.

Key Points to Remember

  • C++ allows throwing objects of user-defined classes as exceptions.
  • Exception handling is type-based, enabling fine-grained control.
  • In inheritance-based exceptions, catch order matters.
  • Constructors can throw and handle exceptions for input validation.
  • User-defined exceptions improve clarity, maintainability, and robustness.
Comment