jeudi 13 mai 2021

Implement functions in separately multiple inherited classes

I have a code generation program that creates a class that has a bunch of (non-pure) virtual functions (GUI programming). The default behavior is to simply exit cleanly on the event occurring.

I would like to add a different implementation to each of these functions, but the catch is I don't want to implement them all in the same class and simply inherit, I want to have the flexibility to change the implementation by changing the class.

I have had an idea that sort of takes the policy design pattern using multiple inheritances with a templated class, but I can't figure out how to retain the base class impl if I decide to not implement a function.

e.g.

#include <iostream>

class Base
{
public:
  virtual void foo()
  {
    std::cout << "Base foo()" << std::endl;
  }

  virtual void bar()
  {
    std::cout << "Base bar()" << std::endl;
  }
};

class impl_foo : public Base
{
public:
  void foo() override
  {
    std::cout << "impl_foo foo()" << std::endl;
  }
};

class impl_bar : public Base
{
public:
  void bar() override
  {
    std::cout << "impl_bar bar()" << std::endl;
  }
};

template<
  typename BAR,
  typename FOO
>
class all : private BAR, FOO
{
public:
  using FOO::foo;
  using BAR::bar;
};


int main()
{
  all<impl_bar, impl_foo> temp;
  temp.foo();
  temp.bar();
}
> ./main
impl_foo foo()
impl_bar bar()

The above code works and runs the templated class foo/bar impl as I expect. If I change the class to say, impl2_foo and template it on that instead of impl_foo, it calls the correct impl of foo.

class impl_foo2 : public Base
{
public:
  void foo() override
  {
    std::cout << "impl_foo2 foo()" << std::endl;
  }
};

...

int main()
{
  all<impl_bar, impl_foo2> temp;
  temp.foo();
  temp.bar();
}

> ./main
impl_foo2 foo()
impl_bar bar()

But the behavior to fall back to the base class impl is lost. I also can't simply add a default to the template like:

template<
  typename BAR = Base,
  typename FOO = Base
>
class all : private BAR, FOO
{
public:
  using FOO::foo;
  using BAR::bar;
};

Since if I don't want to implement more than 1 of the virtual functions, I end up inheriting from Base more than once and it fails to compile.

int main()
{
  all<> temp;
  temp.foo();
  temp.bar();
}

^ Fails to compile

So the behavior I want is: you have a class with a collection of virtual functions. A class inherits from something which at some point in the hierarchy tree inherits from the original class. The implementation of each function is defined in a separate class that can be inherited from, but you have the choice on which function to create a separate implementation for and specify those in the instantiation of the class which contains either the modified impl, or the base case impl.

I also don't want to inherit in a chain since that doesn't give the flexibility to resort back to the base class implementation if want to remove an implementation.

Aucun commentaire:

Enregistrer un commentaire