I’m writing a wrapper around some autogenerated classes to provide a better interface. I’ve written a simplified example to demonstrate the problem.
I have a class A which has a pointer to an object of class X, then I have class B (inherits A) which has a pointer to an object of class Y (inherits X).
That’s all fine, except that I’m unsure what the best way is to store the pointers to X and Y. I need to be able to manipulate collections of objects of class A and B as if they were all A (with pointers to X being all I’d need there), which works fine with my example below.
My actual question is how best to handle the case of class B which needs to manipulate class Y objects rather than class X. I’m sure there is something quite obvious that I’m missing which I could use here. It feels clumsy to have to repeatedly cast this variable every time I use it and define a method with a different name (e.g. getY) for each class that inherits A that I create. There might be many methods like doStuff all of which would have to be calling getY.
class X {
private:
int i;
public:
X(int i) : i(i) {}
int getI() {
return i;
}
};
class Y : public X {
private:
int j;
public:
Y(int i, int j) : X(i), j(j) {}
int getJ() {
return j;
}
};
class A {
protected:
X* x;
public:
A(X* a) : x(a) {}
X* get() {
return x;
}
};
class B : public A {
public:
B(Y* y) : A(y) {}
private:
//I could create a new function for each class like class B
Y* getY() {
return (Y*)x;
}
public:
void doStuff() {
Y* y = getY();
y->getJ();
std::cout << "J: " << y->getJ() << cout::endl;
}
};
Extract from main:
X* x = new X(5);
Y* y = new Y(5,6);
B b(y);
b.doStuff();
One alternative which occurs to me is that when I construct class B I could initialise a pointer of type Y variable pointing at the same location as the one which be set in X. As long as my pointers were const I think that should be safe from the two references ever pointing to different things.
Any ideas most welcome.
Thanks.
Well, the first thing I would do is break the inheritance relationship between A and B. You say they have a common interface, so start by defining this interface:
I assume that A and B share a lot of code (hence the inheritence relationship), so next define a template class to implement the interface and define the common bits:
Finally, define A and B like so:
Virtually all your code should then deal with ILibraryWrapper pointers or references. If some code absolutely must know the concrete type of the wrapped object, then you can do a dynamic cast:
But generally speaking, it’s better to provide all needed functionality in the ILibraryWrapper interface.