Search code examples
c++pointersinheritancetry-catchthrow

Throw a derived class in catch scope


I would like to understand what going wrong in the program that cause that PE which is a derived class, is not catching by the second catch and display the error like I want. In the same way, what I have to correct in order to run this simple example

class myEx
{
    int errNum;
public:
    myEx(int e) : errNum(e) {}
    virtual void printErr() { cout << errNum << " "; }
};
class subEx : public myEx
{
    string errDesc;
public:
    subEx(int e, string d) : myEx(e), errDesc(d) {}
    void printErr()
    {
        myEx::printErr();
        cout << errDesc << " ";
    }
};
int main()
{
    try
    {
        myEx* pME = new subEx(0, "err 0");
        throw pME;
    }
    catch (myEx* p)
    {
        p->printErr();
        subEx PE(1, "err 1");
        throw PE;
    }
    catch (subEx e)
    {
        e.printErr();
    }
}

Solution

  • A try block can throw only 1 exception object at a time. It can have multiple catch blocks to specify different types of exceptions it wants to catch, but only 1 of them will actually be executed at most, the one that most closely matches the type of exception actually thrown.

    If no catch blocks match, the exception propagates the call stack until it finds a higher catch block that does match.

    If a matching catch block wants to throw a new exception (which is perfectly legal), you need a higher try/catch to catch it.

    Also, do not throw/catch exceptions by pointer. Throw them by value instead, and then catch them by reference. Otherwise, you leak the exception object, as the catch won't be able to free it correctly when the pointer goes out of scope.

    Try this:

    class myEx
    {
        int errNum;
    public: 
        myEx(int e) : errNum(e) {} 
        virtual void printErr() const
        {
            cout << errNum << " ";
        } 
    }; 
    
    class subEx : public myEx
    {
        string errDesc;
    public: 
        subEx(int e, string d) : myEx(e), errDesc(d) {}
        void printErr() const
        {
            myEx::printErr();
            cout << errDesc << " ";
        }
    };
    
    int main()
    {
        try
        {
            try
            {
                throw subEx(0, "err 0");
            }
            catch (const myEx &p)
            {
                p.printErr();
                throw subEx(1, "err 1");
            }
        }
        catch (const subEx &e)
        {
            e.printErr();
        }
    }