C++ Rethrow Exceptions

Rethrowing exceptions in C++ allows you to propagate an exception that has been caught in a catch block to be handled by another handler or caller. This is useful when an exception needs to be logged or partially processed before passing it to a higher-level handler for further processing.


Overview of Rethrowing Exceptions

  • Rethrow Syntax: Use a plain throw; statement in a catch block to rethrow the current exception.
  • Purpose: Allows for partial handling or logging of an exception before propagating it.
  • Scope: Rethrowing must occur within the same catch block where the exception was originally caught.

Syntax for Rethrowing Exceptions

</>
Copy
try {
    // Code that may throw an exception
} catch (const std::exception& e) {
    // Handle or log the exception
    throw; // Rethrow the same exception
}

Examples of Rethrowing Exceptions

Example 1: Basic Rethrow of an Exception

This example demonstrates how to catch an exception, log a message, and then rethrow the exception.

</>
Copy
#include <iostream>
#include <stdexcept>

void functionThatThrows() {
    throw std::runtime_error("An error occurred!");
}

int main() {
    try {
        try {
            functionThatThrows();
        } catch (const std::runtime_error& e) {
            std::cerr << "Caught in inner try: " << e.what() << std::endl;
            throw; // Rethrow the exception
        }
    } catch (const std::exception& e) {
        std::cerr << "Caught in outer try: " << e.what() << std::endl;
    }
    return 0;
}

Working of this Program:

  1. Include necessary headers:
    • <iostream>: Used for input/output operations.
    • <stdexcept>: Provides standard exception classes like std::runtime_error.
  2. Define a function that throws an exception:
    • The function functionThatThrows is defined to throw a std::runtime_error with the message "An error occurred!".
  3. Use a nested try-catch block:
    • The outer try-catch block is used to catch exceptions that are rethrown from the inner block.
    • The inner try-catch block contains the call to functionThatThrows and handles the std::runtime_error exception specifically.
  4. Handle the exception in the inner block:
    • If the exception is caught in the inner block, the message "Caught in inner try: An error occurred!" is displayed using std::cerr.
    • The exception is then rethrown using the throw keyword.
  5. Handle the rethrown exception in the outer block:
    • The outer catch block captures the rethrown exception as a general std::exception.
    • The message "Caught in outer try: An error occurred!" is displayed using std::cerr.

Output:

Caught in inner try: An error occurred!
Caught in outer try: An error occurred!

Example 2: Rethrowing in a Function

This example demonstrates rethrowing an exception from a function to the caller.

</>
Copy
#include <iostream>
#include <stdexcept>

void process() {
    try {
        throw std::invalid_argument("Invalid argument encountered!");
    } catch (const std::invalid_argument& e) {
        std::cerr << "Error logged: " << e.what() << std::endl;
        throw; // Rethrow the exception
    }
}

int main() {
    try {
        process();
    } catch (const std::exception& e) {
        std::cerr << "Caught in main: " << e.what() << std::endl;
    }
    return 0;
}

Output:

Error logged: Invalid argument encountered!
Caught in main: Invalid argument encountered!

Best Practices for Rethrowing Exceptions

  • Use Rethrow Judiciously: Only rethrow exceptions when additional processing or logging is necessary.
  • Preserve Original Exception: Avoid modifying the exception when rethrowing to ensure the original context is retained.
  • Rethrow Safely: Ensure that resources are properly cleaned up before rethrowing, using RAII (Resource Acquisition Is Initialization) where applicable.