Home > Software design >  Why is my exception sliced to base class if I catch it with reference to base class?
Why is my exception sliced to base class if I catch it with reference to base class?

Time:10-02

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?

CodePudding user response:

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_; }
  • Related