views:

69

answers:

2

Hi,

I have the following hierarchy of classes

class classOne
{
    virtual void abstractMethod() = 0;
};

class classTwo : public classOne
{
};

class classThree : public classTwo
{
};  

All classOne, classTwo and classThree are abstract classes, and I have another class that is defining the pure virtual methods

class classNonAbstract : public classThree
{
    void abstractMethod();

    // Couple of new methods
    void doIt();
    void doItToo();
};

And right now I need it differently...I need it like

class classNonAbstractOne : public classOne
{
    void abstractMethod();

    // Couple of new methods
    void doIt();
    void doItToo();
};

class classNonAbstractTwo : public classTwo
{
    void abstractMethod();

    // Couple of new methods
    void doIt();
    void doItToo();
};

and

class classNonAbstractThree : public classThree
{
    void abstractMethod();

    // Couple of new methods
    void doIt();
    void doItToo();
};

But all the nonAbstract classes have the same new methods, with the same code...and I would like to avoid copying all the methods and it's code to every nonAbstract class. How could I accomplish that?

Hopefully it's understandable...

+4  A: 
template<class Base>
struct Concrete : Base {
  void abstractMethod();

  void doIt() {
    // example of accessing inherited members:
    int n = Base::data_member; // or this->data_member
    n = Base::method(); // non-virtual dispatch
    n = this->method(); // virtual dispatch

    // since Base is a template parameter, 'data_member' and 'method' are
    // dependent names and using them unqualified will not properly find
    // them
  }
  void doItToo();
};

typedef Concrete<classOne> classNonAbstractOne; // if desired, for convenience

Make sure to give your abstract base classes either a virtual public destructor or make the destructor protected (then it doesn't have to be virtual, but still can be).

Because the template must be parsed with names looked up without yet knowing exactly what Base will be, you need to either use Base::member or this->member to access inherited members.

Roger Pate
+1  A: 

I usually try to avoid inheritance if possible (except for pure abstract classes which define pure interfaces) because it creates a tight coupling. In many cases composition is the better alternative.

Also, things tend to get messy with complex inheritance structures. It's not easy to say from your description what's the best in this particular case. Just pointing this out as a rule of thumb.

bitc
I'll +1 this. Composition > inheritance. If doIt and doItToo have the same code, then put them in the base class. ABC don't have to be all virtual pure methods - they can be normal methods and member vars too.
DeadMG
I can't do it, because my pure virtual methods are for network operations and are therefore platform dependant...
JTom