user3144223
user3144223

Reputation: 13

What() method for std::exception isn't acting virtual?

So in the reference manual, the what() method is described as virtual, but it doesn't seem to be acting that way. (I am compiling with g++ and the c++11 flag)

#include <stdio.h> //printf
#include <iostream> //cout
#include <stdexcept>// std::invalid_argument
using namespace std;

void fn(){
    throw runtime_error("wowwowo");
}

int main(){
    try {fn(); }
    catch(exception a) {cout << a.what() << endl;}
    return 0;
}

The output for this is "std::exception", as opposed to the error message, "wowwowo". However, if I change the catch type to runtime_error, it behaves as expected. I have some code where I would like to catch exceptions that may or may not be runtime_errors, and I suppose I could have multiple catch blocks, but I'm curious as to why the code behaves as it does. Here's the code that prints out the error message:

#include <stdio.h> //printf
#include <iostream> //cout
#include <stdexcept>// std::invalid_argument
using namespace std;

void fn(){
    throw runtime_error("wowwowo");
}

int main(){
    try {fn(); }
    catch(runtime_error a) {cout << a.what() << endl;}
    return 0;
} 

Upvotes: 1

Views: 253

Answers (1)

Vlad from Moscow
Vlad from Moscow

Reputation: 310940

Change this statement:

catch(exception a) {cout << a.what() << endl;}

to this:

catch(const exception &a) {cout << a.what() << endl;}

You have to catch an exception by reference in order for it to use polymorphism. Otherwise, you are slicing the std::runtime_error object so only a std::exception object remains, thus std::exception::what() will be called instead of std::runtime_error::what().

As for the function itself, it is indeed a virtual function.

class exception {
public:
    //...
    virtual const char* what() const noexcept;
};

Upvotes: 11

Related Questions