There might be situation where we want to catch exception, do something and re-throw the same exception. By the way, it is possible to throw an exception from the catch block. The exception thrown from a catch block would be caught by the one level above matching catch block.

Following program shows a wrong way of throwing an exception:

#include <iostream>
 
class Base
{
public:
    virtual void whoami() const
    {
        std::cout << "Base" << '\n';
    }
};
 
class Derived : public Base
{
public:
    void whoami() const override
    {
        std::cout << "Derived" << '\n';
    }
};
 
int main(int argc, char const *argv[])
{
    try
    {
        try
        {
            throw Derived{};
        }
        catch (const Base &ex)
        {
            ex.whoami();
            throw ex;
        }
    }
    catch (const Base &ex)
    {
        ex.whoami();
    }
    return 0;
}
 

When we run this program, we should see following output:

Derived
Base

Although we are throwing the same exception again, why calling .whoami in the outer catch block shows Base? This happens because when we re-throw the exception using throw ex, C++ creates a new exception object using copy initialization where it creates a Base class object because reference is of type Base (this is object slicing effect).

So, outer catch block is getting exception object of type Base and that’s why we see Base in the output.

We can solve this issue by just using throw statement as shown below:

int main(int argc, char const *argv[])
{
    try
    {
        try
        {
            throw Derived{};
        }
        catch (const Base &ex)
        {
            ex.whoami();
            throw;
        }
    }
    catch (const Base &ex)
    {
        ex.whoami();
    }
    return 0;
}

When re-throwing exception like this, C++ does not create a new exception object, it throws the existing object. And so we get the right output when we run the new program.

References

  1. https://www.learncpp.com/cpp-tutorial/rethrowing-exceptions/