c++exceptioninheritancec++98object-slicing

c++ std::exception "what()" message will always only print "std::exception" in a custom exception - why can't I get it to print the contents?


if I do this:

//... in .h header:

class MyCustomException : public std::exception{
  private:
    string message;

  public:
    MyCustomException (string msg); //in .cpp implements "message = msg"
    ~MyCustomException() throw(){ }
    string what(); //implemented to return message.

}
//... other code ... in cpp:

if (<blah blah blah>){
  throw MyCustomException("I want to see THIS message when I fail ... but I don't...");
}

//... more code, in cpp:

//try{<blah...>}
catch(const:: std::exception& e){
   cout << e.what() << endl << flush; //just prints "std::exception" ... same if I use "cerr" instead of cout.
}

Important notes before replying:

The computer the code is on doesn't have outside communication, so I typed this ... so if there is small obvious typos, know I probably have it correct.

Due to my company's legacy industry equipment, I am stuck with C++98, so do not have access to std::current_exception which is with a later version like C++11, I think.

However, I can get #include <cxxabi.h> to work, which allows me to <demangle>(__cxxabivl::__cxa_current_exception_type()->name()) ... but that is still just the name of MyCustomException, not its what() message.

I could try to catch each individual exception and print its what() message ... but there should be a way to do it easier, right?

I found the documentation confusing and only really found a type_info* that I don't think points to the actual original exception object (wherein I could theoretically extract the proper what() message).

Is there a way to add a generic <T> to be used in a catch for any exception so that I can print MyCustomException object's message, and not its super super parent's (i.e. std::exception) virtual what() message? I tried but it didn't work.

Note: Yes, I use catch(const std::exception e) ... yet the "Object Slicing" problem of printing the parent still occurs.

Note: If I catch MyCustomException, I get the proper message.


Solution

  • You are not experiencing "object slicing" since you are not catching the exception by value.

    std::exception::what() is a virtual method, but you are simply not overriding it correctly, which is why MyCustomException::what() is not being called as expected. If you were using C++11 or later, you could use the override keyword to catch this mistake at compile-time, but that option is not available in C++98.

    MyCustomException::what() needs to be declared like the following in C++98 to override std::exception::what():

    const char* what() const throw()
    

    Example:

    #include <exception>
    #include <iostream>
    #include <string>
    
    class MyCustomException : public std::exception {
    public:
        MyCustomException(const std::string& msg) throw() : message(msg) {}
        virtual ~MyCustomException() throw() {}
    
        const char* what() const throw() { return message.c_str(); }
    
    private:
        std::string message;
    };
    
    int main() {
        try {
            throw MyCustomException(
                "I want to see THIS message when I fail ... but I don't...");
        } catch (const std::exception& e) {
            std::cout << e.what() << '\n';
        }
    }
    

    Output:

    I want to see THIS message when I fail ... but I don't...