Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


Tip of the Day
Language: Design Patterns
Expertise: Beginner
Jul 18, 1997

Inheritance design

Question:
Suppose I've got the following class hierarchies:
Surface_Plot
ContourSurface_Plot, child of Surface_Plot

Surface_Data
GridSurface_Data, child of Surface_Data

Surface_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 becoming a 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 used in a lot of places, it might be worthwhile to incorporate it as a 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:

template 
class Surface_Data_Container : public Surface_Plot
{
protected:
   Surface_Data_Container() : data_(dynamic_cast(Surface_Plot::data_))
   {
      assert(data_ != 0);
   }
   T *data_;
};
and then inherit 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..
   }
};
DevX Pro
 
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap
Thanks for your registration, follow us on our social networks to keep up-to-date