我想设计一个通用的 C++ 类,它定义了一个 operator()
函数,该函数在某个点返回数学函数的值。但是,我希望该类能够使用已经定义了 operator()
的对象或使用该类将插入以给出值的值表进行实例化。我想到了以下方法:
class MathFunction
{
MathFunction(Functor& function);
MathFunction(Mat<double> interpolationValues);
double operator()(double radius, double angle);
};
构造函数可以设置成员变量,
double operator()
可以使用 switch 语句来确定如何输出我想要的 double
。不过,这似乎非常不优雅。此类的模板化版本可能有用,但由于这两种方法不共享任何代码,这样做是否明智?模板化版本究竟是如何设计的?
不知道我是否清楚。如果需要任何说明,请发表评论。
编辑:虽然我选择 Useless 的答案是因为它的完整性,但我想强调 dasblikenlight 贡献的速度和清晰度。谢谢。
最佳答案
如果 MathFunction
没有任何通用的实现,它是做什么用的?
如果它的目的是为两个实现提供一个通用接口(interface),请考虑在何处使用它:
MathFunction
的类型,或者在代码中总是静态地知道它使用的是哪种类型 在情况 1 中,使用类似策略模式的东西是合理的。
MathFunction
可以是一个静态类型的包装器分派(dispatch)到虚拟策略,或者您可以编写一个抽象的 MathFunction 基类,并实例化两个具体子类之一。dasblinkenlight 已经演示了 Strategy 版本,所以这里是 ABC 等价的(注意它如何使用工厂函数来隐藏实现细节)
// public header
class MathFunction {
public:
virtual ~MathFunction() {}
virtual double operator() (double radius, double angle) = 0;
};
MathFunction* make_function(Functor& function);
MathFunction* make_function(Mat<double> interpolationValues);
// implementation
class FunctorMathFunction : public MathFunction {
Functor& _function;
public:
FunctorMathFunction(Functor& function) : _function(function) {}
virtual double operator() (double radius, double angle) {
return _function(radius, angle);
}
};
class TableMathFunction : public MathFunction {
Mat<double> _interpolationValues;
public:
TableMathFunction (Mat<double> interpolationValues)
: _interpolationValues(interpolationValues) {}
virtual double operator() (double radius, double angle) {
return ...; // Use _interpolationValues to do calculation
}
};
MathFunction* make_function(Functor& function) {
return new FunctorMathFunction(function);
}
MathFunction* (Mat<double> interpolationValues) {
return new TableMathFunction(interpolationValues);
}
在情况 2 中,模板
MathFunction
是一个不错的选择:您可以(部分)对其进行专门化,或者使用 Strategy 模式的编译时等效项,即在 Policy 类上参数化 MathFunction,它将评估委托(delegate)给它。如果性能是一个问题,保存虚拟函数调用(并启用内联)可能会很有用。template <typename EvaluationPolicy>
class MathFunction
{
EvaluationPolicy eval;
public:
MathFunction() {}
MathFunction(EvaluationPolicy const &ep) : eval(ep) {}
double operator() (double radius, double angle) {
return eval.calc(radius, angle);
}
};
class FunctionPolicy
{
std::function<double(double,double)> func;
public:
FunctionPolicy(std::function<double(double,double)> f) : func(f) {}
double calc(double r, double a) { return func(r, a); }
};
class TablePolicy
{
Mat<double> mat;
public:
TablePolicy(Mat<double> values) : mat(values) {}
double calc(double r, double a) { return ....; }
};
使用 Policy 而不是只编写两个不同的具体类(
FunctionMathFunction
和 TableMathFunction
)的好处在于显示它们的关系,共享不依赖于策略的任何代码,以及能够将不相关的问题拆分为单独的策略。关于c++ - 根据给定的对象类型改变类的行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13881852/