在成员函数上使用外部类是一个好的设计

What is a good design to use external class on member functions?

本文关键字:一个 函数 成员 外部      更新时间:2023-10-16

我有以下设计问题,正在寻找最优雅,甚至更重要的最有效的解决方案,因为这个问题来自性能是一个问题的环境。简单地说,我有一个类"Function_processor",它对实函数进行一些计算(例如,计算实函数的根),我有另一个类"A",它有不同的此类函数,需要使用Function_processor对它们执行计算。

Function_processor应该尽可能通用(例如,不为各种不同的对象提供接口),而只是坚持自己的任务(对任何函数进行计算)。

#include "function_processor.h"
class A {
    double a;
public:
    A(double a) : a(a) {}
    double function1(double x) {
        return a*x;
    }
    double function2(double x){
        return a*x*x;
    }
    double calculate_sth() {
        Function_processor function_processor(3*a+1, 7);
        return function_processor.do_sth(&function1);
    }
};
class Function_processor {
    double p1, p2;
public:
    Function_processor(double parameter1, double parameter2);
    double do_sth(double (*function)(double));
    double do_sth_else(double (*function)(double));
};

显然,我无法像以下示例中那样传递成员函数 A::function1/2(我知道这一点,但这大致是我认为可读的代码)。我也不能使函数 1/2 静态,因为它们使用非静态成员 a。我确信我可以使用像 std::bind 或模板这样的 sth(即使我对这些东西几乎没有任何经验),但我最关心的是我会得到的性能。

我的问题的最佳(漂亮的代码和快速的性能)解决方案是什么?

感谢您的帮助!

无论是从纯 OO 的角度来看,还是从功能或过程 POV 的角度来看,这都不是最好的方法。首先,您的类 A 实际上只不过是一个必须实例化的命名空间。就个人而言,我只是将其函数作为自由浮动的 C 样式函数 - 也许在某个命名空间中,以便您获得某种分类。

以下是在纯 OO 中执行此操作的方法:

class Function
{
    virtual double Execute(double value);
};
class Function1 : public Function
{
    virtual double Execute(double value) { ... }
};
class FunctionProcessor
{
    void Process(Function & f)
    {
         ...
    }
}

这样,您可以实例化Function1FunctionProcessor并将 Function1 对象发送到 Process 方法。您可以从Function派生任何内容并将其传递给进程。

一种类似但更通用的方法是使用模板:

template <class T>
class FunctionProcessor
{
    void Process()
    {
        T & function;
        ...
    }
}

你可以将任何内容作为 T 传递,但在这种情况下,T 成为编译时依赖项,因此您必须在代码中传递它。这里不允许动态的东西!

这是另一个模板化机制,这次使用简单函数而不是类:

template <class T>
void Process(T & function)
{
    ...
    double v1 = function(x1);
    double v2 = function(x2);
    ...
}

你可以这样称呼这个东西:

double function1(double val)
{
    return blah;
}
struct function2
{
    double operator()(double val) { return blah; }
};
// somewhere else
FunctionProcessor(function1);
FunctionProcessor(function2());

您可以将此方法用于任何可以使用正确签名调用的内容:简单的函数,类中的静态方法,函子(如上面的struct function2),std::mem_fun对象,新奇的c ++ 11 lambda,...如果使用函子,则可以在构造函数中传递参数,就像任何对象一样。

最后一个可能是我会做的;如果你知道你在编译时调用什么,它是最快的,也是在阅读客户端代码时最简单的。如果由于某种原因必须非常松散地耦合,我会选择基于第一个类的方法。我个人认为这种情况非常罕见,尤其是当你描述问题时。

如果您仍想使用您的class A,如果不需要成员访问权限,则使所有函数都成为静态函数。否则,请查看std::mem_fun.我仍然不鼓励这种做法。

如果我理解正确,您正在搜索的内容似乎是指向成员函数的指针:

double do_sth(double (A::*function)(double));

但是,对于调用,您还需要类 A 的对象。您也可以将其传递到构造函数中的function_processor中。

不过,不确定它的性能。