Tutorial :Implementing complex inheritance in C++



Question:

I have the following existing classes:

class Gaussian {  public:    virtual Vector get_mean() = 0;    virtual Matrix get_covariance() = 0;    virtual double calculate_likelihood(Vector &data) = 0;  };    class Diagonal_Gaussian : public Gaussian {  public:    virtual Vector get_mean();    virtual Matrix get_covariance();    virtual double calculate_likelihood(Vector &data);  private:    Vector m_mean;    Vector m_covariance;  };    class FullCov_Gaussian : public Gaussian {  public:    virtual Vector get_mean();    virtual Matrix get_covariance();    virtual double calculate_likelihood(Vector &data);  private:    Vector m_mean;    Matrix m_covariance;  };  

As you see, the class Gaussian acts as an interface but doesn't have any implementation. This is all working fine.

Now I want to make an class "AdaptedGaussian" where the data vector provided to the calculated_likelihood will be changed before the likelihood is calculated.

Some requirements:

  • The AdaptedGaussian must be a child-class of Gaussian
  • AdaptedGaussian must be able to "wrap" or "be an instance of" every possible Gaussian class
  • AdaptedGaussian must be constructed from an already existing Gaussian Object

The idea I have now is:

class Adapted_Gaussian : public Gaussian {  private:    Gaussian* m_g;    public:    virtual Vector get_mean() { return m_g->get_mean(); }    virtual Matrix get_covariance() { return m_g->get_covariance(); }    virtual double calculate_likelihood(Vector &data)     {       //do something with data      return g->calculate_likelihood(Vector &data);     }  }   

There are maybe some disadvantages:

  • For every method (and there are more than showed here) a dummy method must be written in the new class
  • If Gaussian is ever extended, and this class would be forgotten, nasty bugs can appear.

Am I doing this in the right way? Or are there better methods to implement this?

Is there maybe a good way to standard delegate every non-implemented method to the same named method of m_g?


Solution:1

Looks good, I think this is a pretty classic implementation of the Adapter pattern. Just don't forget to declare a virtual destructor for your Gaussian class. As for the disadvantages.

  1. The way Java class library deal with the dummy method problem is to create a dummy class that provides empty implementation for every single method. All classes that do not want to implement every single method can just inherit from this dummy class and selectively override methods that interests them.
  2. If you extend your Gaussian class with few more methods, as long as you declare them as pure virtual method you will get a compiler error in your child class file anyway.


Solution:2

As you point out writing a lot of basic pass-through functions is tedious and adds an implied maintenance overhead. Also, having a pointer member implies extra (albeit simple) lifetime management issues of the owned pointer. Probably the simplest way to address these issues is to make AdaptedGaussian a template, templated on the specific instance of Gaussian to be adapted.

template<class BaseGaussian> class AdaptedGaussian : public BaseGaussian  {      virtual double calculate_likelihood(Vector &data)       {           // do something with data          return BaseGaussian::calculate_likelihood(Vector &data);       }  };  

This does rely on all adapted instances of Gaussian being default constructible, or at least conforming to a common constructor signature.

If you want to construct an AdaptedGaussian from an existing XXXGaussian, then so long as the XXXGaussian is itself copyable you can add a suitable constructor:

template<class BaseGaussian> class AdaptedGaussian : public BaseGaussian  {  public:      AdaptedGaussian(const BaseGaussian& other) : BaseGaussian(other)      {      }      // ...  };  


Solution:3

This could maybe also be solved by a Strategy Pattern.

It seams to me, that duffymo also was thinking in this direction with "composition". Change the design in that way, that the base class calls some method of an other object it contains. This object contains the coding for calculate_likelihood. Either the whole method can be deferred or only the modifications (in the second case, the default would be to just do nothing).

E.g.: (corrected version)

class Gaussian {     private:        Cl_Strategy* m_cl_strategy;       public:        Gaussian(Cl_Strategy* cl_strategy) {           m_cl_strategy = cl_strategy;        };        virtual Vector get_mean() = 0;        virtual Matrix get_covariance() = 0;        virtual double _calc_likelihood(Vector &data) = 0;        virtual double calculate_likelihood(Vector &data) {           m_cl_strategy->do_your_worst(this, data);           return _calc_likelihood(data);        };  };  

I hope, I got that one right, my C++ is a little bit dusted ...

_calc_likelihood must be implemented by subclasses and calculate_likelihood binds all together.

Of course, this solution adds a little overhead, but in some situations, the overhead might be OK.


Solution:4

In Java, it's common to have both an interface and an abstract class that implements it to provide default behavior for all methods. (See Joshua Bloch's design of the Collections API in java.util package.) Perhaps that can help you here as well. You'll give clients a choice of using either the interface or the abstract class.

You can also try composition. Pass an instance of an adapted Gaussian to subclasses and defer behavior to it.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »