Question:
Suppose I’ve got the following class hierarchies:
Surface_PlotContourSurface_Plot, child of Surface_PlotSurface_DataGridSurface_Data, child of Surface_DataSurface_Plot contains a Surface_Data object, ContourSurface_Plot contains a GridSurface_Data object.What is the most elegant way to arrange the data members of the
Surface_Plot hierarchy so that the Surface_Plot class can access the GridSurface_Data object’s Surface_Data behaviors, and ContourSurface_Plot can access its extended behaviors? My approach has been to make the xxxData objects pointers, and to have both a GridSurface_Data and Surface_Data pointer referencing the same data member. This route to a solution seems terribly ugly and error-prone. Furthermore, my real hierarchies are much longer, resulting in a plethora of redundant pointers of increasingly sophisticated types.
There must be a cleaner way!
Answer:
You are right ? having two pointers is a problem and could end up becominga maintenance nightmare. The trick is to use the right type in the derived class to access the extended behavior. Consider:
class Surface_Plot{protected: Surface_Data *data_;};class ContourSurface_Plot : public Surface_Plot{public: void useExtendedOperation () { GridSurface_Data * g = dynamic_cast(data); if(g) g->doSomething (); }}; That’s the basic idea. If the GridSurface_Data needs to be usedin a lot of places, it might be worthwhile to incorporate it asa data member and initialize it in the constructor of ContourSurface_Plot.This is similar to your multiple pointer solution. In this case you want to keep a reference in the derived class to prevent accidental deletion.In an implementation I would move the burden of maintaining this extra pointer to another class that will do the cast, etc., as in:
templateand then inheritclass Surface_Data_Container : public Surface_Plot{protected: Surface_Data_Container() : data_(dynamic_cast (Surface_Plot::data_)) { assert(data_ != 0); } T *data_;};
ContourSurface_Plot from Surface_Data_Container:class ContourSurface_Plot : public Surface_Data_Container{public: void useExtendedOperation () { data_->doSomething (); // accesses Surface_Data_Container ::data_ which is the // right type.. }};
Charlie has over a decade of experience in website administration and technology management. As the site admin, he oversees all technical aspects of running a high-traffic online platform, ensuring optimal performance, security, and user experience.




















