我想设计一个通用的 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 而不是只编写两个不同的具体类( FunctionMathFunctionTableMathFunction )的好处在于显示它们的关系,共享不依赖于策略的任何代码,以及能够将不相关的问题拆分为单独的策略。

    关于c++ - 根据给定的对象类型改变类的行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13881852/

    10-11 22:00