4
votes

I have the problem with mixing exceptions and multiple inheritance. Basically I have this code:

#include <exception>
#include <stdexcept>
#include <iostream>

class A : public std::exception
{
public:
    virtual ~A() noexcept {};
};

class B : public A, public std::runtime_error
{
public:
    B() : A{}, std::runtime_error{""}
    {

    }
};

int main()
{
    try {
        throw B{};
    } catch (const std::exception& error) {
        // this catch doesn't work
        std::clog << "Caught!" << std::endl;
    }
}

What I need is to modify it so that exception of class B can be caught as std::exception (for now the terminate handler is called). How can I achieve such behavior? I guess virtual inheritance is needed but I don't see any way to use it in this case.

UPDATE: I need to be able to:
- catch A as A (trivial),
- catch A as std::exception,
- catch B as B (again, trivial),
- catch B as std::exception,
- catch B as std::runtime_error

I know this is a lot of requirements, and maybe it doesn't make much sense, but I need it and I'm just curious:)

UPDATE2: I think the problem is std::runtime_error not derving virtually from std::exception (which would allow me to solve problem by by virtual inheritance in A). Am I right? Still, can it be solved?

UPDATE3: Alan Stokes suggested solution in comments below, which seems to work for me:

Can you split A into two classes - one that implements the functionality B needs, and one that adds in the inheritance from std::exception? Then both A and B could inherit from (say) A_base.

Thanks for that, still if anyone has other good solutions please let me know.

1
Why you need such inheritance? - ForEveR
@ForEveR In my real code class A implements creating stacktrace and is threated as base class for my exceptions hierarchy, and class B is templated class (the template parameter is one of standard exceptions with specialization for std::system_error) which has to mix basic stacktrace functionality and allow catching as type given as template parameter, class A or std::exception (the last one is my problem) - witosx
Since runtime_error already inherits from exception you are facing a Diamond problem. You can use virtual inheritance for either A or runtime_error but I'm not sure it will solve your problem. - Olwaro
@Olwaro: It didn't solved the problem. - witosx
Can you split A into two classes - one that implements the functionality B needs, and one that adds in the inheritance from std::exception? Then both A and B could inherit from (say) A_base. - Alan Stokes

1 Answers

3
votes

Stroustrup recommends to inherit from std::exception virtually, so that there is only one conversion path.

Personally, I find that working out a multiple inheritance scheme is probably over-engineering and prefer a linear inheritance chain... or just none at all.