dcsimg
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

By submitting your information, you agree that devx.com may send you DevX offers via email, phone and text message, as well as email offers about other products and services that DevX believes may be of interest to you. DevX will process your information in accordance with the Quinstreet Privacy Policy.


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

WEBINAR:

On-Demand

Building the Right Environment to Support AI, Machine Learning and Deep Learning


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