views:

175

answers:

3

Suppose I have a class Base which has a member variable A* my_hash. I also have class Extended which inherits from class Base. I also have a class B which extends A.

class Base{
  Base(): my_hash(new A) {}
  //methods which use my_hash
protected:
  A* my_hash;

};

class Extended:public Base{
 //methods which use my_hash from A
 //I cannot have a B* my_other_hash in this class
 //I would like to substitute B* my_hash
 //I cannot let Base create my_hash (of type A*) because that is not what I want.
};

I would like Extended to do the usual (i.e. use everything it inherits from A), except and with one important difference, I want my_hash to be B* instead of A*.
Whenever something accesses my_hash, either via Extended's methods or Base's methods, I would like the methods to be executed to be B*'s.

One thing to try: I cannot have a method call (e.g. create_hash() in Base()) which I redefine in Extended. This does not work as there seems no way to go back up to the class Extended when I create the hash.

I would not like Base to even know about B. How do I do this?

+2  A: 

You could make the Base class into a template on A:

template<typename T>
class Base{
  Base(): my_hash(new T) {}
  //methods which use my_hash
protected:
  T* my_hash;

};

class Extended:public Base<B>{
 ...
};
Autopulated
You'd probably also want a "typedef Base<A> RealBase" or somesuch (more likely rename Base to BasicBase or something.)
Mike Kale
+4  A: 

If the type of 'B' extends 'A', then you could set it up so that you pass the value for 'm_hash' through the constructor (you can also hide this constructor as protected so code that doesn't inherit from 'Base' can't extend it).

e.g.

class Base{
  Base(): my_hash(new A) {}
  //methods which use my_hash
protected:

  A* my_hash;
  Base(A* hash): my_hash(hash) {}
};

class Extended:public Base{
public:
  Extended() : Base(new B) {}
};

Also, if you want new, specialised functions in 'B' that you can call from 'Extended', then you can either store that in another pointer or just cast 'my_hash' to type 'B*'.

Grant Peters
A: 

A template might be the way to go here, as suggested by Autopulated. Another way to do it is in fact to have a B* my_other_hash (like you mention in the question), and then in B's ctor set my_other_hash to my_hash.

class Extended:public Base{
    ExtendedBase(): Base() {
        my_other_hash = my_hash;
    }
}

Then you can access the A methods in Base and the A or B methods in Extended. Make sure to only delete one of them! In Base's dtor or outside the hierarchy if you manage the memory elsewhere.

Mike Kale