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?
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_; }