Post Self
Post Self

Reputation: 1564

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?

Upvotes: 0

Views: 94

Answers (1)

Kenny Ostrom
Kenny Ostrom

Reputation: 5871

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);
    }
};

Upvotes: 1

Related Questions