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
{
publi
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:
I'll leave it to you to translate this to your problem but comment if you have any trouble.
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
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.