c++exceptionthrowobject-slicing

Throw string exception from inherited exception class


I implemented my exception class which inherited from std::exception like the following :

class MyException : public exception
{
public:
    MyException(string exc)
    {
        this->exc = exc;
    }

    const char * what() const throw ()
    {
        return exc.c_str();
    }

private:
    string exc;
};

Now i throw MyException manually and suppose that an exception occurred in my code, But i tested it in two different ways in catch section :

  1. Catch normally catch (const std::exception exc)

    try
    {
        throw MyException("This is an exception");
    }
        catch (const std::exception exc)
    {
        MessageBoxA(NULL, exc.what(), "", MB_OK);
    }
    
  2. Catch with reference catch (const std::exception &exc)

    try
    {
        throw MyException("This is an exception");
    }
        catch (const std::exception &exc)
    {
        MessageBoxA(NULL, exc.what(), "", MB_OK);
    }
    

The first thrown exception string is :

Unknown exception

And the second thrown exception (The one that has & in catch section) is :

This is an exception

Why can't i get my custom exception string while using catch normally without reference(&) and why is it OK by reference?


Solution

  • You are experiencing object slicing.

    This happens when a derived instance is received by value as its base class -- In your case, catching std::exception by value. Your derived class' member is "sliced off" in the process of conversion to the base class.

    Receiving by pointer or by (const) reference is always preferable when you expect to use a parameter polymorphically. For catching a std::exception you should always catch by const reference (I can't really think of a scenario where you wouldn't).