Home > Mobile >  How to re-throw an abstract class error from a catch block
How to re-throw an abstract class error from a catch block

Time:11-08

I need to perform some action inside a catch block then throw the same exception I got:

#include <string>
#include <iostream>
class AbstractError {
public:
    virtual std::string toString() const = 0;
};

class SomeConcreteError : public AbstractError { public:
    std::string toString() const { return "division bt 0"; }
};

class SomeOtherError : public AbstractError { public:
    std::string toString() const { return "null pointer deref"; }
};

void foo(int i)
{
    if (i > 2) { throw SomeConcreteError(); }
    else       { throw SomeOtherError();    }
}

int main(int argc, char **argv)
{
    try { foo(argc); }
    catch (const AbstractError &e)
    {
        std::cout << e.toString() << "\n"; // do some action then re-throw
        throw e; // doesn't work ...
    }
    return 0;
}

Here is the error I get:

main.cpp:28:15: error: expression of abstract class type ‘AbstractError’ cannot be used in throw-expression
   28 |         throw e;
      |               ^

CodePudding user response:

This would throw a copy of e:

throw e;

but it's abstract so that can't be done. You need to rethrow the same exception:

throw;

CodePudding user response:

You've tried one of the two forms of the throw keyword, and you want the other:

    catch (const AbstractError &e)
    {
        std::cout << e.toString() << "\n"; // do some action then re-throw
        throw;
    }

The description is pretty clear:

  1. Rethrows the currently handled exception. Abandons the execution of the current catch block and passes control to the next matching exception handler (but not to another catch clause after the same try block: its compound-statement is considered to have been 'exited'), reusing the existing exception object: no new objects are made.

Or alternatively from [expr.throw]/3:

A throw-expression with no operand rethrows the currently handled exception. The exception is reactivated with the existing exception object; no new exception object is created. The exception is no longer considered to be caught.

As an aside, is there a particular reason you're calling your method toString() instead of the what() used in the std::exception hierarchy?

  • Related