0

I have a parent class which as a member contains an array of pointers to objects of the same type as itself. I have another class that derives from the parent class. I want that the derived class uses an array of pointers to objects of its own (not the parent class). The deriving class calls methods on those objects that are stored in the array of pointers; it calls both methods which are defined and implemented in the derived class as well as in the base class. The code below obviously doesn't compile as parent contains no member z (in derived::doX()). I could dyanamic_cast(p[i]).z before accessing z, but I would have to do that on EVERY method in b at runtime. If I hide "p" in the derived class (by casting the p's during object construction), I essentially get two arrays of pointers p, however, I want all methods operate on the same objects (residing in p). I tried templates but ran into a recursive issue. Any idea how to solve this?

#include <iostream>
#include <stdlib.h>
using namespace std;

class parent{
protected:
  parent** p;
  int num;
  int x;
public:
  parent(int _num, parent** _ps);
  virtual void doX();
  virtual void print();
};

class derived : public parent {
protected:
  //derived** p;
  int z;
public:
  derived(int _num, parent** _ps) : parent(_num, _ps){};
  virtual void doX();
  virtual void print();
};

void parent::doX(){
  for(int i=0;i<num;i++){
    p[i]->x = 1;
  }
}
void parent::print(){  cout << "x " << x << endl;
}

parent::parent(int _num, parent** _ds){
  num=_num;
  p = _ds;
}

void derived::doX(){
  for(int i=0;i<num;i++){
    p[i]->z = 2;
  }
  parent::doX();
}
void derived::print(){
  cout << "x " << x << endl;
  cout << "z " << z << endl;
}

int main(){
  const int NUM = 2;
  parent** ps = (parent**)malloc(sizeof(parent)*NUM);
  for(int i=0; i< NUM; i++){
    ps[i] = new derived(NUM, ps);
  }

  ps[0]->doX();
  ps[0]->print();
  ps[0]->print();
}
hlitz
  • 635
  • 6
  • 24

1 Answers1

0

You are on the right track! You should use the "p" defined in the parent class. In the derived class setter methods you enforce that the derived type must be used (as the parameter type). For instance your constructor for defined will be:

derived(int _num, derived** _ps) : parent(_num, _ps){};

Then, when you're using p in the derived methods, you know that p is really a derived type, and you can safely cast it.

krsteeve
  • 1,794
  • 4
  • 19
  • 29
  • yes but then I have a cast in every method (which in principle is unnecessary) it introduces overhead and the code is very performance critical. It's also not very nice to have dynamic_casts all over the place – hlitz Apr 23 '13 at 02:33
  • You can *safely* cast it - use C-style cast. You have already guaranteed that it is a valid cast and you don't need the overhead of dynamic_cast – krsteeve Apr 23 '13 at 04:17
  • Saying that, you may want to re-think your design. Consider looking at some design patterns such as the composite pattern. http://en.wikipedia.org/wiki/Composite_pattern – krsteeve Apr 23 '13 at 04:23
  • I used C++ static_cast<>() which works fine and is a little cleaner than C-style – hlitz Apr 23 '13 at 18:19