Implementing multiple interfaces in c++

I have the interface hierarchy as follows:

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

class B: public A
{
public:
void testB() = 0;
};

class C: public A
{
public:
void testC() = 0;
};

Now, I want to implement these interfaces by the same hierarchy, that is a Base class AImpl, BImpl and CImpl but I am not sure how to derive them from their corresponding interfaces.

Please help. Thanks in advance.


You can implement each individial interface using a separate template and then chain the templates to construct the derived object as if from building blocks. This method was also used by venerable ATL library to implement COM interfaces (for those of us old enough).

Note that you don't need virtual inheritance for that.

I slightly modified you example for a more complex derivation C -> B -> A to show how this method scales easily:

#include <stdio.h>

// Interfaces

struct A
{
    virtual void foo() = 0;
};

struct B : A
{
    virtual void testB() = 0;
};

struct C : B
{
    virtual void testC() = 0;
};

// Implementations

template<class I>
struct AImpl : I
{
    void foo() { printf("%s\n", __PRETTY_FUNCTION__); }
};

template<class I>
struct BImpl : I
{
    void testB() { printf("%s\n", __PRETTY_FUNCTION__); }
};

template<class I>
struct CImpl : I
{
    void testC() { printf("%s\n", __PRETTY_FUNCTION__); }
};


// Usage

int main() {
    // Compose derived objects from templates as from building blocks.
    AImpl<A> a;
    BImpl<AImpl<B> > b;
    CImpl<BImpl<AImpl<C> > > c;

    a.foo();

    b.foo();
    b.testB();

    c.foo();
    c.testB();
    c.testC();
}

Output:

void AImpl<I>::foo() [with I = A]
void AImpl<I>::foo() [with I = B]
void BImpl<I>::testB() [with I = AImpl<B>]
void AImpl<I>::foo() [with I = C]
void BImpl<I>::testB() [with I = AImpl<C>]
void CImpl<I>::testC() [with I = BImpl<AImpl<C> >]

While I'd normally think twice before suggesting multiple inheritance. If your needs really aren't more complicated than you said, then just inherit both interface and implementation virtually.

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

class B: virtual public A
{
public:
  void testB() = 0;
};

class C: virtual public A
{
public:
  void testC() = 0;
};

class AImpl : virtual public A
{
 ...
}

class BImpl : virtual public B, virtual public AImpl
{
 ...
}

The virtual inheritance will make sure there is only one sub-object A shared between B and AImpl. So you should be in the clear. The object size will increase, however. So if that's an issue, rethink your design.


I think what you are asking is, how do I create a second class hierarchy of implementations that mirrors my "interace" class hierarchy. You want to do this to reduce the coupling between your interface and implementations. Your problem is that you think your implementation classes should extend your interface classes but also the "natural" inheritance hierarchy in the impl classes, as in

   AImpl
  ^    ^
  |    |
BImpl  CImpl

I suggest you look at the GoF (Gang of Four) Bridge pattern that describes this pattern. Actuall, the example in the book is better than that on Wikipedia but can't seem to find it online. Here's a rough (ascii) UML:

Window <>imp----------------------------> WindowImpl
^    ^                                    ^        ^
|    |                                    |        |
|   TransientWindow                       |     PMWindowImp
IconWindow                              XWindowImp

In the example above, you have a Window class whose #imp references the impementation. So, your IconWindow implementation will have #imp referencing, say XWindowIconWindow to perform the real work but clients will only ever reference it through the IconWindow instance. This reduces your recompile overhead.

The salient points to make are:

  • Separate class hierarchy for window types (normal window, icon window, dialog) and window implementations (X-windows, PMWindows). They can be extended independently.
  • Operations are implemented in terms of abstract operations on WindowImp So, operations are abstracted from platform specifics.
  • Reduce prolieferation of classes that occurs if you try to mix the abstractions and multiple implementations.

I'll leave it to you to translate this to your problem but comment if you have any trouble.