【发布时间】:2018-10-12 08:19:35
【问题描述】:
我知道在 SO 上还有另一个非常相似的 post。但我认为这有点不同。这里的主要问题不是讨论 一些 方法的优点或缺点(尽管它很自然地出现),而是 为了达到多态行为而存在哪些方法以及什么是最好的方法一些标准(见下文)。
假设我有一个具有以下结构的类
class Evaluator
{
public :
double Evaluate( double x )
{
/*something here*/
}
};
我们可以选择不同的实现 Evaluate 函数从一个实例到另一个实例。我想根据以下标准找到最佳(在某种意义上)解决方案。
-
Evaluate函数的实现(Evaluate究竟是什么)在实例的构造步骤中确定 - 添加
Evaluate函数的新实现应该尽可能简单 -
Evaluate函数旨在成为 abstract 类的方法 - 不仅要使用
Evaluate方法,还要使用它的派生方法。所以如果函数和它的导数一起存在会很好
我找到的解决方案有助于了解我想要达到的目标。
使用指向函数的指针
//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 )
使用虚函数
//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 )
讨论
虽然第二种方法对我的个人问题更有吸引力(请参阅最后一个标准),但我在那里看到了危险的 new 运算符。这实际上是一个问题吗?适当的析构函数会解决它吗?我提供的解决方案还有什么问题?主要问题是:什么是做我想做的事的最佳方式?。
【问题讨论】:
-
“我看到那里有危险的 new 运算符。它真的有问题吗” 是的。所以只需使用
std::unique_ptr<>和std::make_unique()代替。那么,以后就不用记得写一个对应的同样丑陋的delete了。 -
std::function<double(double)>是另一种选择。 -
为什么第二个更有吸引力?在我看来,它似乎对对象着迷。
-
@molbdnilo,此外,我不仅想使用
Evaluate本身,还想使用它的派生词。所以我可以很容易地添加ReturnPrime函数并在具体情况下覆盖它,这样函数和它的派生词就在一起了。 -
您的第二个解决方案是众所周知的“策略”模式。
标签: c++ function class function-pointers