Search code examples
c++multiple-inheritanceduck-typing

C++ multiple inheritance and duck typing


I am trying to find a way to express a common base type for two objects that inherit a pair of similar interfaces.

See the code below : it is apparent that there should be a possible common base type for fb1 and fb2 (for example, something like IFizzBuzz).

Does anyone know if that is possible (without requiring to templates if possible :-)

Thanks !

#include <memory>
#include <iostream>

struct IFizz {
  virtual void DoFizz() = 0;
};
struct IBuzz {
  virtual void DoBuzz() = 0;
};

struct Fizz : public IFizz {
  void DoFizz() override {
    std::cout << "Fizz\n";
  } 
};

struct Buzz1 : public IBuzz {
  void DoBuzz() override {
    std::cout << "Buzz1\n";
  } 
};
struct Buzz2 : public IBuzz {
  void DoBuzz() override {
    std::cout << "Buzz2\n";
  } 
};

struct FizzBuzz1 : public Fizz, public Buzz1 {
};
struct FizzBuzz2 : public Fizz, public Buzz2 {
};

// Expected "Base type" of FizzBuzz1 and FizzBuzz2
struct IFizzBuzz : public IFizz, public IBuzz {
};

int main()
{
  {
    FizzBuzz1 fb1;
    fb1.DoFizz();
    fb1.DoBuzz();
  }
  {
    FizzBuzz2 fb2;
    fb2.DoFizz();
    fb2.DoBuzz();
  }
  // { 
  //   // The line below is not legit and does not compile
  //   std::unique_ptr<IFizzBuzz> ifb(new FizzBuzz1());
  //   ifb->DoFizz();
  //   ifb->DoBuzz();
  // }
  return 0;
}

Solution

  • There are 3 common base classes for FizzBuzz1 and FizzBuzz2

    • IFizz
    • IBuzz
    • Fizz

    Without changing the definitions of those two, there is no way to have them also have IFizzBuzz as a base.

    You can however have an class that derives IFizzBuzz and delegates to one of the two, e.g.

    template <typename FizzBuzz>
    struct Wrapper : IFizzBuzz
    {
        void DoFizz() final { fizzBuzz.DoFizz(); }
        void DoBuzz() final { fizzBuzz.DoBuzz(); }
    private:
        FizzBuzz fizzBuzz;
    }
    

    This can then be used, e.g.

    std::unique_ptr<IFizzBuzz> ifb = std::make_unique<Wrapper<FizzBuzz1>>();
    ifb->DoFizz();
    ifb->DoBuzz();
    ifb = std::make_unique<Wrapper<FizzBuzz2>>();
    ifb->DoFizz();
    ifb->DoBuzz();