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
try
block contains code that may throw an exception. - If
y
is zero, athrow
statement is used to signal a division by zero error. - The
catch
block 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
try
block throws an integer exception, which is caught by the firstcatch
block. - The second
try
block throws a string exception, which is caught by the secondcatch
block.
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
try
block throws aruntime_error
exception. - The first
catch
block catches theruntime_error
exception and prints the error message using thewhat
method. - The second
catch
block is a general handler for any otherexception
types.
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
MyException
class inherits fromstd::exception
and overrides thewhat
method to return a custom error message. - The
main
function throws aMyException
object, which is caught by thecatch
block 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
func
function throws aruntime_error
exception and catches it using acatch
block. - The
catch
block infunc
re-throws the exception using thethrow
statement. - The
main
function 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
func
function is declared withnoexcept
, indicating that it does not throw exceptions. - The
main
function 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.