Widening pointers
Sometimes one object needs services of another object. One of natural
ways to implement this is to use pointer to that object. We can suppose
pointer to this object is passed in constructor. And everything's fine
till it is needed to descend a more functional class from the previous one
and when that new class needs wider services from the object that it has
pointer to. So the helper object also becomes a base for a more advanced
class. But the problem is, how the new class can access new functionality?
It has only pointer to the old helper object. There are many possible ways
of resolving this:
- Add a new pointer of type of new helper class - waste of memory -
old and new pointer point to the same object.
- Add all functionality to the old helper class in form of pure
virtual functions - better, but still wrong - if we would have to
descend third generation, we would have to recompile all files,
besides that, it is stupid for some generic object to have all methods
used in hierarchy.
- Use multiple virtual inheritance - but it is to be used for more parallel
relations between classes, and here, only one of them needs to know
about the other. And, you cannot decide of the type of helper object
at the run-time.
- Use templates - generally ok, but sometimes it is better or even
needed to decide about types at run-time
My solution is a compilation of those above. It consumes zero memory
and zero time, and it is completely safe from the point of view of
programmer despite the use of static conversions.
The new class will use the inherited pointer to the old helper class.
It should be converted statically to new helper class. A inline method can
be added to make using that simpler - method, which converts the pointer
to the old class and returns the new one. Alternatively, you can use properties.
But what with that safety, you might think. What, if one converts the
new class to the old class, and assigns to the pointer object of old
helper class, not the new one? The answer is: he don't.
We should make sure the only way to assign the helper object to the
real object is in constructor of the real object. And each real object can
be costructed only with helper class of specified kind. In this way, it is
sure the object is right.
There are two kinds of vehicles: cars and sportscars. Cars can drive on
roads, but sports cars only on highways, that are of course roads, also.
Cars cannot race, while sportscars can. One can race only on highways.
That's the classes implementing this:
class vehicle;
class road {
public:
void drive(vehicle
*);
};
class car : public vehicle {
protected:
road *r;
road *road()
{ return r; }
public:
void drive()
{ road()->drive(this); }
car(road *r)
: r(r) {}
};
class highway : public road {
public:
void race(vehicle
*, vehicle *);
};
class sportscar : public car {
protected:
highway
*road() { return static_cast<highway *>(r); }
public:
void
race(sportscar *co) { road()->race(this, co); }
sportscar(highway *co) : car(co) {}
};
So, that is, I guess, all.
|