kim366 kim366 -4 years ago 127
C++ Question

How to call same name virtual functions of parents

#include <stdio.h>

struct Base
{
virtual void thatSomething() = 0;
void doSomething() {thatSomething(); }
};

struct DerOne : Base
{
virtual void thatSomething() override {std::puts("DerOne"); }
};

struct DerTwo : Base
{
virtual void thatSomething() override {std::puts("DerTwo"); }
};

struct Joined : DerOne, DerTwo
{
Joined()
{
Base::doSomething();
}
};

int main()
{
Joined j;
return 0;
}


Output:


DerOne


Why is only
thatSomething
of
DerOne
called? I expect it to be called of both parent classes of
Joined
.

@hvd mentioned that with multiple inheritance I have multiple instances of
Base
.

Also worth mentioning: When I flip the inheritance of
Joined
(
struct Joined : DerTwo, DerOne
), I get


DerTwo


as output instead.

Only doing
doSomething()
in the
Joined
constructor will give me an error for ambiguity of the function call.

When I use virtual inheritance, I again get an ambiguity error.

If it is not possible to call both functions this way, what other options do I have in order to achieve that with only one line of code that does not address the intermediate classes in the hierarchy or even no line of code implicitly?

Answer Source

The quick fix is simply to have Joined call both, explicitly. (edited to override the virtual function)

virtual void Joined::thatSomething() override
{
    DerOne::thatSomething();
    DerTwo::thatSomething();
}

If that doesn't take care of everthing, then maybe inheritance isn't a good fit. Composition used to be used a lot more, before all the OOP, and it is still powerful.

If you're expecting a specific thing to happen when you call thatSomething(), but you don't know which one to call, then maybe it's simply not true that Joined is-a DerOne and is-a DerTwo. But it's much easier for Joined to have-a DerOne, and have-a DerTwo, and as many more as you want.

#include <list>
#include <memory>
struct DerHandler
{
    std::list<std::unique_ptr<DerBase>> handlers;

    void addHandler(DerBase *p) { 
        handlers.push_back(std::unique_ptr<DerBase>(p)); 
    }

    void doSomething() { 
        for (std::unique_ptr<DerBase> &rp : handlers)
            rp->thatSomething();
    }
};

struct Joined : DerHandler {
    Joined(){
        addHandler(new DerOne);
        addHandler(new DerTwo);
    }
};
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download