Search code examples
c++overridingmultiple-inheritancepure-virtual

Override pure virtual method with parallel base class method?


Say I have class Foo with a pure virtual function say and class Bar with a method say and I want to implement class FooBar which inherits from Foo and Bar with Foo::say being overrode by Bar::say. I could do something as follows:

#include <iostream>

class Foo {
public:
    virtual void say() = 0;
};

class Bar {
public:
    void say() {
        std::cout <<"I am a Bar." << std::endl;
    }
};

class FooBar : public Foo, public Bar {
public:
    void say() override {
        Bar::say();
    }
};

int main() {
    FooBar foobar;
    foobar.say();  // I want to print "I am a Bar."
    return 0;
}

But this just makes FooBar::say a function that calls Bar::say. It is a very minor annoyance but is there a way to actually just make FooBar override Foo::say directly with Bar::say? Would making FooBar::say inline reliably accomplish this? I realize I could make Bar inherit from Foo and FooBar inherit only from Bar but this would not be appropriate in the actual project this example is an analogous to.


Solution

  • #include <iostream>
    
    class ISay {
    public:
        virtual void say() = 0;
    };
    
    class Bar: public virtual ISay {
    public:
        void say() override {
            std::cout <<"I am a Bar." << std::endl;
        }
    };
    
    class FooBar : public virtual ISay, public Bar {};
    
    int main() {
        FooBar foobar;
        foobar.say();  // Prints "I am a Bar."
    }
    

    This is known as dominance in virtual inheritance.

    Some argue that in order to support this, one should always inherit interfaces virtually.


    Virtual inheritance has two main costs (well maybe more):

    • Initialization of the virtually inherited common class sub-object, that upmost base class, is specified in the most derived class. Specifications in classes intermediate in the inheritance chain(s), are ignored.
    • There can be some overhead for member function calls, because the this pointer may have to be adjusted.