C++ Custom Exceptions
In this page:
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?
// 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;
}
Login to try C/C++/Java/PHP code in the editor
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
// 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;
}
Login to try C/C++/Java/PHP code in the editor
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
// 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;
}
Login to try C/C++/Java/PHP code in the editor
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
// 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;
}
Login to try C/C++/Java/PHP code in the editor
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
// 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;
}
Login to try C/C++/Java/PHP code in the editor
- Not inheriting from
std::exception, socatch (std::exception&)cannot catch it. - Forgetting to override
what(), so it returns a generic message. - Writing
what()withoutconst noexcept, which does not match the base signature.
Chapter Quiz — Complete all 5 topics to unlock
0/5 topics done
Complete these topics first: