c++c++11exceptiongccobject-slicing

Why is my exception sliced to base class if I catch it with reference to base class?


So I've written a small C++ class as follows:

class bad_hmean : public std::logic_error {
    const char *nature_;
    char *what_;

public:
    bad_hmean(const char *fname);

    ~bad_hmean() { delete[] what_; }

    const char *what() { return what_; }
};

inline bad_hmean::bad_hmean(const char *fname):nature_("BAD HARMONIC MEAN VALUES"), std::logic_error("BAD HARMONIC MEAN VALUES")
{
    int len = strlen(fname) + strlen(nature_)+3;
    what_ = new char [len];
    strcpy(what_, fname);
    strcat(what_, ": ");
    strcat(what_, nature_);
}

And I've tried testing it inside the following main:

void fun1() { throw bad_hmean(__func__); }

int main()
{
    try
    {
        fun1();
    } catch(std::exception& e)
    {
        std::cout << e.what();
    }
}

And when I run it I encounter one problem that I can't wrap my head around. Even though I throw the exception by value and catch it by reference, slicing still happens because the output of my code is: BAD HARMONIC MEAN VALUES. But if I catch the exception as a reference to bad_hmean the output is what I intended it to be: fun1: BAD HARMONIC MEAN VALUES.

Does anyone know why does this happen?


Solution

  • bad_hmean doesn't override what() correctly. It should match the signature of the base class what as:

    const char *what() const noexcept { return what_; }
    //                 ^^^^^ ^^^^^^^^
    

    BTW: It's better to use override specifier (since C++11) to ensure that the function is overriding a virtual function from a base class. E.g.

    const char *what() const noexcept override { return what_; }