Introduction
Exception handling in C++ is a mechanism that allows a program to deal with unexpected events or errors that occur during runtime. By using exceptions, you can separate error-handling code from regular code, making the program more readable and maintainable. The core keywords used for exception handling in C++ are try, catch, and throw.
Basic Concepts
- try block: Contains code that might throw an exception.
- catch block: Contains code that handles the exception.
- throw statement: Used to signal the occurrence of an exception.
Syntax
Basic Syntax
try {
// Code that may throw an exception
} catch (exception_type e) {
// Code to handle the exception
}
Examples
Example 1: Basic Exception Handling
#include <iostream>
using namespace std;
int main() {
try {
int x = 10;
int y = 0;
if (y == 0) {
throw "Division by zero error!";
}
int z = x / y;
cout << z << endl;
} catch (const char* e) {
cout << "Caught exception: " << e << endl;
}
return 0;
}
Output
Caught exception: Division by zero error!
Explanation
- The
tryblock contains code that may throw an exception. - If
yis zero, athrowstatement is used to signal a division by zero error. - The
catchblock catches the exception and prints an error message.
Example 2: Multiple Catch Blocks
#include <iostream>
using namespace std;
int main() {
try {
throw 20;
} catch (int e) {
cout << "Caught an integer exception: " << e << endl;
} catch (const char* e) {
cout << "Caught a string exception: " << e << endl;
}
try {
throw "An error occurred";
} catch (int e) {
cout << "Caught an integer exception: " << e << endl;
} catch (const char* e) {
cout << "Caught a string exception: " << e << endl;
}
return 0;
}
Output
Caught an integer exception: 20
Caught a string exception: An error occurred
Explanation
- The first
tryblock throws an integer exception, which is caught by the firstcatchblock. - The second
tryblock throws a string exception, which is caught by the secondcatchblock.
Example 3: Standard Exception Classes
C++ provides a hierarchy of standard exception classes in the <exception> header.
#include <iostream>
#include <exception>
using namespace std;
int main() {
try {
throw runtime_error("Runtime error occurred");
} catch (const runtime_error& e) {
cout << "Caught runtime_error: " << e.what() << endl;
} catch (const exception& e) {
cout << "Caught exception: " << e.what() << endl;
}
return 0;
}
Output
Caught runtime_error: Runtime error occurred
Explanation
- The
tryblock throws aruntime_errorexception. - The first
catchblock catches theruntime_errorexception and prints the error message using thewhatmethod. - The second
catchblock is a general handler for any otherexceptiontypes.
Example 4: Custom Exception Classes
You can define your own exception classes by inheriting from std::exception.
#include <iostream>
#include <exception>
using namespace std;
class MyException : public exception {
public:
const char* what() const noexcept override {
return "My custom exception occurred";
}
};
int main() {
try {
throw MyException();
} catch (const MyException& e) {
cout << "Caught MyException: " << e.what() << endl;
}
return 0;
}
Output
Caught MyException: My custom exception occurred
Explanation
- The
MyExceptionclass inherits fromstd::exceptionand overrides thewhatmethod to return a custom error message. - The
mainfunction throws aMyExceptionobject, which is caught by thecatchblock and prints the custom error message.
Example 5: Re-throwing Exceptions
You can re-throw an exception using the throw statement without any arguments inside a catch block.
#include <iostream>
using namespace std;
void func() {
try {
throw runtime_error("Error in func");
} catch (...) {
cout << "Caught exception in func, re-throwing..." << endl;
throw; // Re-throw the exception
}
}
int main() {
try {
func();
} catch (const exception& e) {
cout << "Caught exception in main: " << e.what() << endl;
}
return 0;
}
Output
Caught exception in func, re-throwing...
Caught exception in main: Error in func
Explanation
- The
funcfunction throws aruntime_errorexception and catches it using acatchblock. - The
catchblock infuncre-throws the exception using thethrowstatement. - The
mainfunction catches the re-thrown exception and prints the error message.
Example 6: Exception Specifications (Deprecated in C++11, Removed in C++17)
Prior to C++11, exception specifications were used to specify which exceptions a function might throw. They are now deprecated and replaced by noexcept.
#include <iostream>
#include <exception>
using namespace std;
void func() noexcept {
// This function is specified to not throw exceptions
cout << "This function does not throw exceptions" << endl;
}
int main() {
try {
func();
} catch (...) {
cout << "Caught exception" << endl;
}
return 0;
}
Output
This function does not throw exceptions
Explanation
- The
funcfunction is declared withnoexcept, indicating that it does not throw exceptions. - The
mainfunction callsfunc, and no exceptions are thrown or caught.
Conclusion
Exception handling in C++ allows you to manage runtime errors in a controlled and predictable manner. By using try, catch, and throw statements, along with standard and custom exception classes, you can write robust and maintainable code. Understanding and effectively using exception handling is essential for writing reliable C++ programs.