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.