c++ooppolymorphismmultiple-inheritance

C++ Multiple Inheritance: Implementing interfaces with overlapping virtual functions


I'm trying to design a class hierarchy in C++ where I have a base interface FooInterface with a pure virtual function foo(), and another interface FooBarInterface that should extend FooInterface and add an additional function bar(). I then have a class Foo that implements foo() from FooInterface, and a class FooBar that inherits from Foo and FooBarInterface and implements bar(). My goal is to have the func function accept a std::shared_ptr to any object that implements both foo() and bar().

#include <memory>

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

class FooBarInterface : public FooInterface {
public:
    virtual void bar() = 0;
};

class Foo : public FooInterface {
public:
    void foo() override {};
};

class FooBar : public Foo, public FooBarInterface {
public:
    void bar() override {};
};

void func(std::shared_ptr<FooBarInterface> fb) {}

int main() {
    func(std::make_shared<FooBar>());
}

Note: omitting virtual destructor.

However, this code does not compile probably because that foo() in FooBarInterface is not overridden in FooBar, even though FooBar inherits from Foo, which implements foo().

How should I modify my code? Or do you have any design pattern that I should refer to?


Solution

  • I got lost in the Foos and the Bars and the Interfaces, so I'm going to rewrite the class hierarchy, keeping the same structure:

    struct Base {
        virtual void foo() = 0;
    }
    
    struct Intermediate1 : Base {
    };
    
    struct Intermediate2 : Base {
        void foo();
    }
    
    struct Derived : Intermediate1, Intermediate2 {
    };
    
    Derived d; // error: can't create object of an abstract type
    

    An object of the Derived has two subobjects of type Base, one coming through Intermediate1 and the other coming through Intermediate2. So it has two different functions foo, one coming through Intermediate1 and one coming through Intermediate2. Since Intermediate1 does not override Base::foo (and Derived also doesn't override it), it's still a pure virtual function, so Derived is an abstract class and cannot be instantiated.

    On the other hand (and how many folks picture inheritance of "interfaces" (quoted because C++ doesn't have a formal notion of an "interface")), a similar hierarchy could look like this:

    struct Base {
        virtual void foo() = 0;
    }
    
    struct Intermediate1 : virtual Base {
    };
    
    struct Intermediate2 : virtual Base {
        void foo();
    }
    
    struct Derived : Intermediate1, Intermediate2 {
    };
    
    Derived d; // okay, via "dominance"
    

    Note the added virtual for the classes derived directly from Base. Now an object of type Derived has only one subobject of type Base, and the dominance rule says that in Derived, Intermediate2::foo overrides Base::foo, even though there is no override in Intermediate1. So Intermediate1 itself is an abstract class, but Derived is not, even though it doesn't override Base::foo; the override through Intermediate2 is sufficient.