I know there is another very similar post here on SO. But I think it's a bit different. The main question here is not a discussion of advantages or disadvantages of some methods (though it appears naturally) but what methods exist in order to reach polymorphic behavior and what is the best one with respect to some criteria (see below).
Suppose I have a class with the following structure
class Evaluator
{
public :
double Evaluate( double x )
{
/*something here*/
}
};
where we can choose different implementation of Evaluate
function from instance to instance. I want to find optimal (in some sense) solution with respect to the following criteria.
- Implementation of the
Evaluate
function (whatEvaluate
exactly is) is determined at the construction step of an instance - It should be as simple as possible to add new implementation of the
Evaluate
function Evaluate
function is intended to be a method of an abstract class- Not only
Evaluate
method is intended to be used but also its derivative. So it would be good if function and its derivative live together
Solutions that I've found could help to understand what I want to reach.
Using pointer to a function
//somewhere in someheader.h
#include <cmath>
namespace evals
{
inline double Sin( double x ) { return sin(x); }
inline double Sigmoid( double x ) { return 1. / ( 1. + exp( -x ) ); }
}
//somewhere in Evaluator.h
class Evaluator
{
protected :
double (*_eval)( double );
public :
Evaluator( double (*eval)( double ) ) : _eval( eval ) { }
double Evaluate( double x ) { return _eval( x ); }
};
//somewhere in test.cpp
#include "someheader.h"
#include "Evaluator.h"
Evaluator e( &evals::Sin );
e.Evaluate( 3.14159 );//returns sin( 3.14159 )
Using virtual functions
//somewhere in someheader2.h
#include <cmath>
namespace evals
{
class AbstractEvaluate
{
public :
virtual double Return( double x ) = 0;
};
//concrete evals
class Sin : public AbstractEvaluate
{
public :
double Return( double x ) { return sin( x ); }
};
class Sigmoid : public AbstractEvaluate
{
public :
double Return( double x ) { return 1. / ( 1. + exp( -x ) ); }
};
}
//somewhere in Evaluator2.h
#include <string>
#include "someheader2.h"
class Evaluator
{
protected :
AbstractEvaluate* _eval;//cannot have an instance, only a pointer
public :
Evaluator( std::string evalName )
{
//according to some rule return pointer to desired concrete evaluate class e.g.
if( evalName == "Sin" ) { _eval == new evals::Sin; }
else if( evalName == "Sigmoid" ) { _eval == new evals::Sigmoid; }
else { /*some default behavior*/ }
}
double Evaluate( double x ) { return _eval->Return( x ); }
}
//somewhere in test.cpp
#include "Evaluator2.h"
Evaluator e( "Sin" );
e.Evaluate( 3.14159 );//returns sin( 3.14159 )
Discussion
While the second approach is more attractive for my personal problem (see the last criterion) I see the dangerous new
operator there. Is it actually a problem and would an appropriate destructor resolve it? What else could be a problem with solutions I provided? And the main question: what is the best way to do what I want?.