Search code examples
c++c++11inheritancefacade

c++ class design, base class inheritance, or facade design pattern


I have a dumb c++ design question. Is there a way for one class to have the same method names (hence, the same API) of the methods found in several classes?

My current situation is that I have a situation where I have classes

struct A
{
    void foo() { std::cout << "A::foo" << std::endl;}
    void boo() { std::cout << "A::boo" << std::endl;}
};

struct B
{
    void moo() { std::cout << "B::moo" << std::endl;}
    void goo() { std::cout << "A::goo" << std::endl;}
};
.... imagine possibly more

What I really want is another class that acts an interface for those of these functionalities. I might be misinterpreting as the facade design pattern for a simple interface that hides the complexity of instantiating classes above but still use their same interface.

struct C 
{
    void foo() { ... }
    void boo() { ... }
    void moo() { ... }
    void goo() { ... }
};

For small number of methods shown above this is feasible by either declaring structs A and B or passing them in as parameters to struct C and call the methods of A and B in C but this is impracticable if A has 40 methods and B has 30 has methods. Redeclaring 70 methods with the same name in C to call the underlying methods of A and B seemed like a lot of redundancy for no reason if I could do better.

I thought of a second solutions of using a base class

struct base
{
    void foo() { }
    void boo() { }

    void moo() { }
    void goo() { }
};

struct A : public base
{
    void foo() { std::cout << "A::foo" << std::endl;}
    void boo() { std::cout << "A::boo" << std::endl;}
};

struct B : public base
{
    void moo() { std::cout << "B::moo" << std::endl;}
    void goo() { std::cout << "A::goo" << std::endl;}
};

To try and use a shared_ptr that has all the function definitions. e.g

std::shared_ptr<base> l_var;
l_var->foo();
l_var->boo();
l_var->moo();
l_var->goo();

That still doesn't quite give me what I want because half of the methods are defined in struct A while the other half is in struct B.

I was wondering if multiple inheritance would do the trick but in school I heard it's bad practice to do multiple inheritance (debugging is hard?)

Any thoughts or recommendations? Basically it's easier to manage struct A and B (and so on as it's own class for abstraction purposes). But would like the flexibility of somehow calling their methods in some wrapper where this complexity is hidden from the user.


Solution

  • I think that

    Redeclaring 70 methods with the same name in C to call the underlying methods of A and B

    is the right path.

    It is tempting to use multiple inheritance in cases like this to avoid writing pass-through code but I think that is generally a mistake. Prefer composition over inheritance.

    I would question whether your user really wants to deal with one interface with 70 methods but if that's really what you want then I don't see why it is "impractical" to write the code in C:

    class C {
        A a;
        B b;
    public:
        void foo() { return a.foo(); }
        void boo() { return a.boo(); }
        void moo() { return b.moo(); }
        void goo() { return b.goo(); }
        // ...
    };
    

    Live demo.

    This has the advantage that you can easily change your mind in the future and replace A and B with something else without changing the interface of C.

    You can hide the implementation of C further by using the PIMPL idiom or by splitting C into an abstract base class C and an implementation CImpl.