Am I using inheritance correctly?

Started by
2 comments, last by JohnBolton 18 years ago
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!
Advertisement
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
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 functionpublic:		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.
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 );            ...        }        ...    }; 
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!

This topic is closed to new replies.

Advertisement