Rethrowing An Exception In C++ - C++ Programming Tutorial
C++ Course / Exception Handling / Rethrowing An Exception In C++

Rethrowing An Exception In C++

BLUF: Mastering Rethrowing An Exception In C++ is a critical step in becoming a proficient C++ developer. This lesson provides a deep dive into the syntax, performance considerations, and real-world applications of this concept.
Key Performance Insight: Rethrowing An Exception In C++

C++ is renowned for its efficiency. Learn how Rethrowing An Exception In C++ enables low-level control and high-performance computing in the tutorial below.

An exception that is caught within a try block can be handled using one or more catch blocks. In some scenarios, it is necessary to catch the exception using a single catch block and then rethrow it. This is done when the catch block at the top of the call stack is capable of handling the specific exception. This concept is known as rethrowing an exception.

Propagating an exception by rethrowing it with its original type and details enables it to move up the call stack for further handling. This technique proves beneficial in scenarios where various exceptions need to be managed across different levels of a program or when additional tasks must be performed before resolving the exception.

Example code:

Example

#include <iostream>
void innerFunction() {
    try {
        // Some code that may throw an exception
        throw std::runtime_error("Exception occurred!");
    } catch (const std::exception& e) {
        std::cout<< "Caught exception in innerFunction: " <<e.what() << std::endl;
        throw;  // Rethrow the caught exception
    }
}
void outerFunction() {
    try {
innerFunction();
    } catch (const std::exception& e) {
        std::cout<< "Caught exception in outerFunction: " <<e.what() << std::endl;
        // Perform additional operations or handle the exception here
    }
}
int main() {
    try {
outerFunction();
    } catch (const std::exception& e) {
        std::cout<< "Caught exception in main: " <<e.what() << std::endl;
        // Handle the exception at the highest level
    }

    return 0;
}

Output:

Output

Caught exception in innerFunction: Exception occurred!
Caught exception in outerFunction: Exception occurred!

Explanation:

In this instance, the innerFunction triggers a std::runtime_error exception. This exception is then rethrown using throw; within the catch block located in innerFunction. This action signals that the catch block within the outerFunction will once more capture the exception. The main function serves as the topmost handler, where the exception can be intercepted ultimately.

Rethrowing exceptions allows you to choose how your program handles them and ensures that they are caught and handled at the appropriate levels.

  • An exception's type is preserved when it is rethrown. When an exception is rethrown using the throw; command , it is basically passed up the call stack to be caught and handled by another catch block. The original type of the exception is retained, enabling catch blocks at higher levels to handle particular sorts of exceptions effectively.
  • Rethrowing allows for additional processing: You can carry out more operations or log additional information about the exception or change its status before rethrowing it. For instance, you might add debug information, add extra context, or encapsulate the original exception inside another exception to give the higher-level catch block more useful information.
  • Catching exceptions by reference: When throwing an exception again, it's crucial to catch it by reference rather than by value (for instance, const std::exception& ). When an exception is caught by reference, it is ensured that the exception object will remain valid even after being caught and rethrown numerous times during the exception handling procedure.
  • Exceptions rethrown and not caught at any stage of the call stack are known as uncaught exceptions . The exceptions not being caught can be handled by the std::terminate function , which ceases the code without any stack unwinding or cleaning steps.
  • Exception propagation: Throwing exceptions again causes them to advance the call stack until they eventually stop in a catch block, where they can be handled properly. Any function in the call stack can stop the spreading of the exception by catching it and rethrowing it. Exceptions can be dealt with in a manner that is appropriate for the circumstance in which they occur using this strategy.
  • Rethrowing with a new exception: You have the option of throwing a new exception in place of the old one when rethrowing an exception. To accomplish this, make a fresh exception object and throw it inside the catch block. Using this method, you can add information to the initial exception before it is caught again higher up the call stack.

Rethrowing Nested Exceptions: Sometimes exceptions can be nested, meaning one exception is raised within the catch block of another. When a nested exception is rethrown, it becomes part of the outer exception's std::nested_exception. This allows you to handle the outer and nested exceptions independently if needed.

Example

try {
    try {
        throw std::runtime_error("Nested exception");
    } catch (const std::exception& nested) {
        std::throw_with_nested(std::logic_error("Outer exception"));
    }
} catch (const std::exception& outer) {
    // Handle the outer exception and potentially access the nested exception
    try {
        std::rethrow_if_nested(outer);
    } catch (const std::exception& nested) {
        // Handle the nested exception
    }
}

Input Required

This code uses input(). Please provide values below:

Logic Practice
Install Logic Practice
Add to home screen for a faster app-like experience