c++ - 使用仿函数模板或继承库

标签 c++ templates inheritance

我正在编写一个数值库,我有一些基于函数及其导数的算法。这些必须由用户作为仿函数提供,例如

struct Function{
    double operator()(double x, double y){return x*x+y*y);}
};
struct DerivativeX{
    double operator()(double x, double y){return 2*x);}
};
//more derivatives...

现在我的算法声明如下:

template<class F, class F_X, class F_Y>
struct Algorithm
{
    Algorithm( F f, F_X fx, F_Y fy):f_(f), fx_(fx), fy_(fy){}
    double someFancyComputation( double input) { 
        //call f_(double,double), fx_(double,double) and fy_(double,double);
    private:
    F f_;
    F_X fx_;
    F_Y fy_;
    //more other stuff...
};

所有的 STL 都使用模板化算法,并且在 C++11 中对模板编程大惊小怪,我觉得使用模板非常现代和酷。 然而,现在让我烦恼的是,为了使用这个算法,用户必须显式地编写所有模板参数:

//construct functors 
Algorithm<Function, DerivativeX, DerivativeY> alg( f, fx, fy);

(假设有 6 个导数。要写的东西很多) 其次,不可能在运行时选择函数集(派生函数),因此我正在考虑在模板上使用继承。

我有两个问题: 首先,您认为在这种情况下使用继承是个好主意,还是我可以使用其他设计模式?

其次,不幸的是,我对库中继承的使用和陷阱不是很有经验,所以您能否展示或解释在这种情况下如何正确完成继承?

编辑:所以经过一些研究我可以想出

struct aBinaryFunction{
    double operator()( double x, double y) = 0;
    ~aBinaryFunction(){}
}; 
struct Algorithm{
    Algorithm( aBinaryFunction* f, aBinaryFunction* fx, aBinaryFunction* fy):f_(f), fx_(fx), fy_(fy){}
    double someFancyComputation( double input) { 
        //call *f_(double,double), *fx_(double,double) and *fy_(double,double);}
    private:
    aBinaryFunction * f_, fx_, fy_;
    //more other stuff...
};
//in main create functors and then call
Algorithm alg(f,fx,fy);

作为一个可能的实现。现在,所有用户都必须编写从我的库类派生的函数,并在调用 someFancyComputation 时小心确保 f fx 和 fy 仍在范围内。这是好的做法还是被认为是限制性的?我对这段代码中的原始指针也感到很不自在,难道没有更好的实现方式吗?

最佳答案

在 C++ 中,你有很多工具......

  • 在编译时选择算法时,模板是合适的。

  • 虚函数适用于运行时选择。

  • 还有许多其他的可能性,如 std::function、函数指针、成员函数指针。

  • 此外,您可以使用 make_something 函数(类似于标准库中的函数,如 make_uniquemake_shared 来替换构造函数调用, make_pair...). 顺便说一句,我认为构造函数模板推导计划用于即将到来的标准。

所以本质上,如果用户选择要在算法中使用的函数,则必须使用基于运行时多态性的解决方案。如果选择是在编译时进行的,那么选择权在您手中。基于模板的解决方案可能会更快,因为编译器可以优化特定情况。但是,并非在所有情况下它都有用,因为如果您在同一程序中使用许多算法,它也可能会增加代码大小。

假设 someFancyComputation 不是微不足道的,并且您想将该算法应用于用户选择或许多编译时类型(如 DerivativeX,Y, Z... ) 基于继承(或上面提到的其他替代方案)的解决方案将是更可取的,特别是如果你的算法只需要使用 double 。

如果某些部分是动态的而其他部分是静态的(比如可能使用 long double),您也可以适本地混合使用这两种方法。

关于c++ - 使用仿函数模板或继承库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45253651/

相关文章:

c++ - 模板特化 : does not match any template declaration

php - 奇怪的 PHP 行为,基类和派生类的字段名称相同,克隆实例

c++ - 3D 表面的 segmentation 算法

c++ - 如何对成对的 vector 进行排序?

C++ 使用模板来避免编译器检查 boolean 值

Python 3 : Returning a new child class instance from an inherited method, 当子构造函数的参数多于父构造函数时

ios - 从泛型类继承初始值设定项

c++ - 当全局函数需要指向 impl 的指针时,如何防止 impl 细节出现在头文件中?

c++ - 在编译时通过模板自动判断类型是否为抽象基类

c++ - 对象池设计模式问题