← Back to C++ Course | Chapter 12: Exception Handling | Lesson 4 of 5

C++ Custom Exceptions

A custom exception is an error type you make yourself with a name that fits your program, like a special warning sign for your own playground. It makes problems easier to understand.
Syntax
cpp
class CustomException {
public:
  std::string message;
  CustomException(std::string msg) : message(msg) {}
};

try {
  throw CustomException("text");
} catch (CustomException &e) {
  // e.message
}

Why Custom Exceptions?

The exceptions built into the standard library are useful but generic; defining your own exception types lets you create error categories that map precisely onto your application's own business logic, which makes debugging and targeted error handling far cleaner.

Example: Why Custom Exceptions?

cpp
// Include std::cout and std::cin
#include <iostream>
// Include std::string
#include <string>

// Define the type InvalidAgeError
class InvalidAgeError {
// Members below can be accessed from outside the class
public:
	std::string message = "Age cannot be negative";
};

// Program execution starts in main()
int main() {
	// Try code that might throw an exception
	try {
		// Throw an exception to signal an error
		throw InvalidAgeError();
	// Handle the exception if one was thrown
	} catch (InvalidAgeError &e) {
		std::cout << e.message << std::endl;
	}
	return 0;
}

Creating a Basic Exception Class

At its simplest, a custom exception class is just an ordinary class with whatever data and methods you decide it needs — you throw instances of it and catch them by that specific class type, just like any standard exception.

Example: Creating a Basic Exception Class

cpp
// Include std::cout and std::cin
#include <iostream>
// Include std::string
#include <string>

// Define the type MyException
class MyException {
// Members below can be accessed from outside the class
public:
	std::string message;
	MyException(std::string msg) : message(msg) {}
};

// Program execution starts in main()
int main() {
	// Try code that might throw an exception
	try {
		// Throw an exception to signal an error
		throw MyException("Something broke");
	// Handle the exception if one was thrown
	} catch (MyException &e) {
		std::cout << e.message << std::endl;
	}
	return 0;
}

Inheriting from std::exception

The professional way to build a custom exception is to inherit from std::exception and override its virtual what() method.

Doing so lets generic catch blocks written for std::exception handle your custom exceptions too, without needing to know about your specific type.

Example: Inheriting from std::exception

cpp
// Include std::cout and std::cin
#include <iostream>
#include <exception>

// Define the type MyException
class MyException : public std::exception {
// Members below can be accessed from outside the class
public:
	const char *what() const noexcept override {
		// Send "Custom exception occurred" back to the caller
		return "Custom exception occurred";
	}
};

// Program execution starts in main()
int main() {
	// Try code that might throw an exception
	try {
		// Throw an exception to signal an error
		throw MyException();
	// Handle the exception if one was thrown
	} catch (std::exception &e) {
		std::cout << e.what() << std::endl;
	}
	return 0;
}

Custom Exceptions with Custom Data

Because your exception is a real class, it can carry custom member data along with the failure — an error code, a file path, a timestamp — giving the code that catches it far richer information than a bare error message alone.

Example: Custom Exceptions with Custom Data

cpp
// Include std::cout and std::cin
#include <iostream>
#include <exception>

// Define the type ValidationError
class ValidationError : public std::exception {
// Members below can be accessed from outside the class
public:
	int errorCode;
	ValidationError(int code) : errorCode(code) {}
	const char *what() const noexcept override {
		// Send "Validation failed" back to the caller
		return "Validation failed";
	}
};

// Program execution starts in main()
int main() {
	// Try code that might throw an exception
	try {
		// Throw an exception to signal an error
		throw ValidationError(422);
	// Handle the exception if one was thrown
	} catch (ValidationError &e) {
		std::cout << e.what() << " code=" << e.errorCode << std::endl;
	}
	return 0;
}

Practical Usage in Validation

In practice, custom exceptions are typically thrown from inside validation logic or system-level operations, where they communicate exactly what went wrong to whatever code further up the stack is responsible for deciding how to respond.

Example: Practical Usage in Validation

cpp
// Include std::cout and std::cin
#include <iostream>
#include <exception>

// Define the type InvalidAgeError
class InvalidAgeError : public std::exception {
// Members below can be accessed from outside the class
public:
	const char *what() const noexcept override {
		// Send "Age must be non-negative" back to the caller
		return "Age must be non-negative";
	}
};

void checkAge(int age) {
	if (age < 0) throw InvalidAgeError();
}

// Program execution starts in main()
int main() {
	// Try code that might throw an exception
	try {
		checkAge(-5);
	// Handle the exception if one was thrown
	} catch (std::exception &e) {
		// Print to the console with cout
		std::cout << e.what() << std::endl;
	}
	return 0;
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Not inheriting from std::exception, so catch (std::exception&) cannot catch it.
  2. Forgetting to override what(), so it returns a generic message.
  3. Writing what() without const noexcept, which does not match the base signature.
🔒

Chapter Quiz — Complete all 5 topics to unlock

0/5 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.