Introduction
Exception handling in C++ is a powerful mechanism that helps manage and respond to runtime errors in a controlled way. The try
, catch
, and throw
keywords are the fundamental building blocks of exception handling in C++. These keywords allow you to separate error-handling code from regular code, improving code readability and maintainability.
try Block
A try
block contains code that might throw an exception. If an exception occurs, it is "thrown" out of the try
block.
Syntax
try {
// Code that may throw an exception
}
catch Block
A catch
block contains code that handles the exception thrown by the try
block. You can have multiple catch
blocks to handle different types of exceptions.
Syntax
catch (exception_type e) {
// Code to handle the exception
}
throw Statement
A throw
statement is used to signal the occurrence of an error (exception). When an exception is thrown, control is transferred to the appropriate catch
block.
Syntax
throw exception;
Example: Basic Exception Handling
Let’s look at a simple example where we handle division by zero using exception handling.
Code Example
#include <iostream>
using namespace std;
int main() {
int a = 10;
int b = 0;
double result;
try {
if (b == 0) {
throw "Division by zero error!";
}
result = a / b;
cout << "Result: " << result << endl;
} catch (const char* e) {
cout << "Exception: " << e << endl;
}
return 0;
}
Output
Exception: Division by zero error!
Explanation
- The
try
block contains code that might throw an exception. - If
b
is zero, athrow
statement is used to signal a division by zero error. - The
catch
block catches the exception and prints an error message.
Multiple Catch Blocks
You can have multiple catch
blocks to handle different types of exceptions.
Example: Multiple Catch Blocks
#include <iostream>
using namespace std;
int main() {
try {
throw 20; // Throw an integer
} catch (int e) {
cout << "Integer exception caught: " << e << endl;
} catch (const char* e) {
cout << "String exception caught: " << e << endl;
}
try {
throw "A string exception"; // Throw a string
} catch (int e) {
cout << "Integer exception caught: " << e << endl;
} catch (const char* e) {
cout << "String exception caught: " << e << endl;
}
return 0;
}
Output
Integer exception caught: 20
String exception caught: A string exception
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.
Standard Exception Classes
C++ provides a standard hierarchy of exception classes defined in the <exception>
header. The base class for all standard exceptions is std::exception
.
Example: Standard Exception Classes
#include <iostream>
#include <exception>
using namespace std;
int main() {
try {
throw runtime_error("Runtime error occurred");
} catch (const runtime_error& e) {
cout << "Runtime error: " << e.what() << endl;
} catch (const exception& e) {
cout << "Exception: " << e.what() << endl;
}
return 0;
}
Output
Runtime error: Runtime error occurred
Explanation
- The
try
block throws aruntime_error
exception. - The
catch
block catches theruntime_error
exception and prints the error message using thewhat
method.
Custom Exception Classes
You can define your own exception classes by inheriting from std::exception
or any of its derived classes.
Example: Custom Exception Class
#include <iostream>
#include <exception>
using namespace std;
// Custom exception class
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 << "Exception: " << e.what() << endl;
}
return 0;
}
Output
Exception: 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.
Re-throwing Exceptions
You can re-throw an exception using the throw
statement without any arguments inside a catch
block. This is useful if you need to perform some actions when an exception is caught and then let a higher-level catch
block handle it.
Example: Re-throwing Exceptions
#include <iostream>
using namespace std;
void func() {
try {
throw runtime_error("Exception in func");
} catch (...) {
cout << "Handling exception in func, re-throwing..." << endl;
throw; // Re-throw the exception
}
}
int main() {
try {
func();
} catch (const exception& e) {
cout << "Caught exception: " << e.what() << endl;
}
return 0;
}
Output
Handling exception in func, re-throwing...
Caught exception: Exception 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.
Conclusion
The try
, catch
, and throw
keywords in C++ are essential for exception handling, allowing you to manage runtime errors in a controlled and predictable manner. By using these keywords, you can write robust and maintainable code that separates error-handling logic from the main logic. Understanding and effectively using these keywords is crucial for writing reliable C++ programs.