Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Inheritance from same grandparent - merge implementations?

for a certain project I have declared an interface (a class with only pure virtual functions) and want to offer users some implementations of this interface.

I want users to have great flexibility, so I offer partial implementations of this interface. In every implementation there is some functionality included, other functions are not overridden since they take care about different parts.

However, I also want to present users with a fully usable implementation of the interface as well. So my first approach was to simply derive a class from both partial implementations. This did not work and exited with the error that some functions are still pure virtual in the derived class.

So my question is if there is any way to simply merge two partial implementations of the same interface. I found a workaround by explicitely stating which function I want to be called for each method, but I consider this pretty ugly and would be grateful for an mechanism taking care of this for me.

#include <iostream>

class A{
    public:
        virtual void foo() = 0;
        virtual void bar() = 0;
};

class B: public A{
    public:
        void foo(){ std::cout << "Foo from B" << std::endl; }
};

class C: public A{
    public:
        void bar(){ std::cout << "Bar from C" << std::endl; }
};

// Does not work
class D: public B, public C {};

// Does work, but is ugly
class D: public B, public C {
    public:
        void foo(){ B::foo(); }
        void bar(){ C::bar(); }
};

int main(int argc, char** argv){
    D d;
    d.foo();
    d.bar();
}

Regards, Alexander


The actual problem is about managing several visitors for a tree, letting each of them traverse the tree, make a decision for each of the nodes and then aggregate each visitor's decision and accumulate it into a definite decision.

A separation of both parts is sadly not possible without (I think) massive overhead, since I want to provide one implementation taking care of managing the visitors and one taking care of how to store the final decision.

like image 644
aweinert Avatar asked Jul 08 '26 20:07

aweinert


1 Answers

Have you considered avoiding the diamond inheritance completely, providing several abstract classes each with optional implementations, allowing the user to mix and match default implementation and interface as needed?

In your case what's happening is that once you inherit to D, B::bar hasn't been implemented and C::foo hasn't been implemented. The intermediate classes B and C aren't able to see each others' implementations.

If you need the full interface in the grandparent, have you considered providing the implementation in a different way, possibly a policy with templates, and default classes that will be dispatched into to provide the default behavior?

like image 82
Mark B Avatar answered Jul 10 '26 09:07

Mark B