2

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.

Chirag Desai
  • 1,249
  • 1
  • 10
  • 22
Aarkan
  • 3,811
  • 6
  • 40
  • 54

4 Answers4

7

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> >]
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • While I liked other answers too, I am accepting this as an answer, because it is very close to my existing design. – Aarkan May 20 '13 at 17:02
5

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.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
2

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.

wmorrison365
  • 5,995
  • 2
  • 27
  • 40
  • +1 on the right lines, but maybe not quite the right pattern. The problem is the derived interfaces and the derived implementations are unrelated. I interpret the OP as wanting derived interfaces that encapsulate extensions implemented by the derived implementations. To adapt the GoF example, I would remove `TransientWindow` and `IconWindow` and replace them with `PMWindow` and `XWindow`, so you end up with a hierarchy of interfaces that mirrors the hierarchy of implementations. Lakos 1996 _Large Scale C++ Software Design_ presents a pattern called Protocol Hierarchy that may be relevant. – Oktalist May 20 '13 at 13:47
  • Having said that, if the OP's design can be made to fit the Bridge pattern, then that would be preferable; keeping the interface narrow and avoiding a combinatorial explosion of classes. – Oktalist May 20 '13 at 15:01
0

Do

class BImpl : public B {
    // code ...
}

but in B, declare the functions as virtual so the compiler will force you to implement them in BImpl

Felype
  • 3,087
  • 2
  • 25
  • 36