Sign in to follow this  
Repetit

Am I using inheritance correctly?

Recommended Posts

Repetit    122
Hey! I have written a few classes which encapsulates funtionality needed for handling mathematical functions. This includes stuff like drawing them, finding intersections and so forth. I have done this by having base classes for each feature, for example:
class CFunctionPlot;           // handles plotting of function
class CFunctionIntersection;   // handles finding intersections with other functions
...
I then have a class for the function in question, for example cosine or a polynomial:
class CFunc_Cos : public CFunctionPlot
{
... stuff specific for cosine functions...
}

class CFunc_Polynomial : public CFunctionPlot
{
...stuff specific for polynomials...
}
The math function classes (CFunc_Cos for example) derive from the base classes whose functionality they need. In the example above, CFunc_Cos and CFunc_Polynomial are only able to draw themselves. The base class gets to know about the math function (cosine for example) through an overridden function, which takes a parameter x and returns the corresponding function value. Now, is this how inheritance was intended to be used? It seems really nice to me, and it makes it easy to reuse my code. Thanks!

Share this post


Link to post
Share on other sites
Nuno1    161
If I understand you correctly then yes, that is what inheritence is about.

post your classes , it may become more abstract then that and we can give you more clear directions.

but it seems you are on the right track understanding the foundations.

cheers and good luck,
Nuno1

Share this post


Link to post
Share on other sites
Repetit    122
Thanks for the quick answer! Here comes the classes:


class CFunctionPlot
{
private:
double m_step;
double m_x1, m_x2; // plot interval
BOOL m_bDashed;
COLORREF m_colPlot;

virtual double m_fn(const double x)const{return 0;} // the function


public:
CFunctionPlot();
~CFunctionPlot();

void SetStep(const double step);
void SetStyle(const BOOL bDashed);
void SetColor(const COLORREF colPlot);
void SetInterval(const double x1, const double x2);

void Plot(const HDC hDC, const CoordSys* pCoordSys)const;
};

class CFn_Sin : public CFunctionPlot
{
private:
double m_amplitude;
double m_frequency;
double m_phase;

double m_fn(const double x)const{return sin(x*m_frequency+m_phase)*m_amplitude;}

public:
CFnPlot_Sin() : m_amplitude(0.0f), m_frequency(0.0f), m_phase(0.0f) {};
~CFnPlot_Sin(){};

void SetParameters(double amp, double freq, double phase){m_amplitude=amp;m_frequency=freq;m_phase=phase;}
double Evaluate(double x)const;
};




I would then make an instance of CFn_Sin, set the appropriate parameters using the memberfunctions, and call the Plot() function. I have only one feature class now (CFunctionPlot) but my plan is to have a class for every feature. This could for example be CFunctionIntersection or CFunctionIntegration.

Share this post


Link to post
Share on other sites
JohnBolton    1372
What you are doing is not normal, and (IMHO) wrong in your case. It might be possible to justify using inheritance that way, but there are better ways to it.

Generally, inheritance expresses an is-a relationship. For example, you might derive a Car or a Bicycle class from a Vehicle class -- a car is a vehicle and a bicycle is a vehicle. In your case, is a cosine function a plot? That seems pretty weird.

Also, classes are usually used to represent things. You are using a class to represent a function. Now, that is not necessarily wrong, in fact it is used quite often (look up "functor"). But in your case, it is a little strange. Consider just making the functions functions instead of classes.

Here is what I suggest you do. Rather than deriving Cosine from FunctionPlot, do something like this:
    class Function
{
...
virtual float operator()( float x ) = 0;
...
};
class Cosine : public Function
{
...
float operator()( float x ) { return cos( x ); }
...
};
class Plotter
{
...
void Plot( Function const & f, ... )
{
...
y = f( x );
...
}
...
};

int main( int argc, char *argv[] )
{
Cosine c( ... );
Plotter p( ... );

p.Plot( c, ... );
}
In this example, the classes Function and Cosine are "functors", i.e. a class that acts as a function, using the () operator. Functors might be a little confusing, so you could write it like this instead:
    class Function
{
...
virtual float Compute float x ) = 0;
...
};
class Cosine : public Function
{
...
float Compute( float x ) { return cos( x ); }
...
};
class Plotter
{
...
void Plot( Function const & f, ... )
{
...
y = f.Compute( x );
...
}
...
};

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this