views:

100

answers:

2

In my class design I ran into the following problem:

class MyData
{   
   int foo;
};

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

class AbstraktB : public AbstraktA
{
public:
    virtual void B() = 0;
};

template<class T>
class ImplA : public AbstraktA
{
public:
    void A(){ cout << "ImplA A()";  }       
};

class ImplB : public ImplA<MyData>, public AbstraktB
{
public:
     void B(){ cout << "ImplB B()"; }   
};

void TestAbstrakt()
{
    AbstraktB *b = (AbstraktB *) new ImplB;
    b->A();
    b->B();
};

The problem with the code above is that the compiler will complain that AbstraktA::A() is not defined.

Interface A is shared by multiple objects. But the implementation of A is dependent on the template argument. Interface B is the seen by the outside world, and needs to be abstrakt.

The reason I would like this is that it would allow me to define object C like this: Define the interface C inheriting from abstrakt A. Define the implementation of C using a different datatype for template A.

I hope I'm clear. Is there any way to do this, or do I need to rethink my design?

+8  A: 

You have two paths of inheritance from AbstracktA, you implement AbstraktA::A() only in one of them, so the compiler complains.

You probably want to inherit virtually from AbstraktA in both case so that there is only one AbstraktA base object (add virtual before AbstraktA).

AProgrammer
Thank you!! That was all. What an easy fix:) I remember now that I've read about virtual inheritance before but because I never had to use it in practice I completely forgot about it.I feared I had to rethink my design because I couldn't come up with an alternative solution that would solve this in a good way. Thanks again.
0x80
This works, but leads to a warning from the compiler:"warning C4250: 'ImplB' : inherits 'ImplA<T>::ImplA<T>::A' via dominance"Is this something to be concerned about?
Talvalin
@lalithv, it is something to be concerned if that isn't what you want. In this case it is what is wanted. (I think this warning is in the category "no very common, has most false positive than true, difficult to avoid cleanly by reorganizing the code in the false positive case")
AProgrammer
A: 

I forgot to add virtual destructors to the base classes. This leads to runtime malloc errors I believe.

AbstraktB *b = new ImplB;
b->A();
b->B();
delete b;

In debug mode, at the delete statement, GCC gives me: malloc: * error for object 0x60e2c4: pointer being freed was not allocated

I solved this by changing the base classes to:

class AbstraktA
{
public:
    virtual ~AbstraktA(){};
    virtual void A() = 0;
};

class AbstraktB : virtual public AbstraktA
{
public:
    virtual ~AbstraktB(){};
    virtual void B() = 0;
};
0x80