成员属性是C ++中的函数

时间:2012-03-25 22:45:05

标签: c++ class function arguments

我正在尝试自学一些C ++,作为一个初始项目,我想创建用于对单个变量的函数执行牛顿方法的代码。我想创建一个类ObjectiveFunction来存储目标函数,一阶导数和二阶导数的用户定义函数。

我希望ObjectiveFunction的构造函数取0到3个参数,其中参数本身就是函数:

// ObjectiveFunction.h
// Class definition for an Objective Function object.

#ifndef OBJECTIVE_H
#define OBJECTIVE_H

class ObjectiveFunction
{
    public:
        // Constructors

        // Default constructor
        ObjectiveFunction();

        // Constructor with just objective function.
       ObjectiveFunction(double f(double));

       // Constructor with objective function and derivative function.
       ObjectiveFunction(double f(double), double fp(double));

       // Constructor with objective, derivative, and second derivative functions.
       ObjectiveFunction(double f(double), double fp(double), double fpp(double));

       // Methods
       void setObjectiveFunction(double f(dobule));
       void setDerivativeFunction(double f(double));
       void setSecondDerivativeFunction(double f(double));

       double evalObjectiveFunction(double);
       double evalDerivativeFunction(double);
       double evalSecondDerivativeFunction(double);

    private:
       // Storage for the functions.
       // This is the part I'm not sure of.

       // Attempt with function pointers
       double (*objFunc)(double);
       double (*d1Func)(double);
       double (*d2Func)(double);

};

#endif // OBJECTIVE_H

我如何创建本身就是函数的私有数据成员。我想创建函数对象(除了私有)可以像foo.obj_func(3.0)foo.deriv_func(3.0)那样访问,其中obj_func由构造函数根据用户传递给的函数设置类。

这样做的正确方法是什么?如果有一种方法不依赖于使用指向函数对象的指针,那将是最好的,但我想如果这是唯一的方法那么我就必须学习它。

4 个答案:

答案 0 :(得分:3)

使用std::function<double(double)>。这将使您能够轻松存储所有功能类型。

答案 1 :(得分:0)

在决定实施技术之前,你有几个选择......

创建ObjectiveFunction后,您需要一种方法来在设置后更改功能吗?您是否希望对您接受的“函数”更加灵活(即'functor'(基本上是实现函数调用运算符的任何东西)是否可以接受)?你是否希望使用ObjectiveFunction的东西能够使用任何ObjectiveFunction可互换的,而不管它在构造它时作为参数给出了什么函数?

你在这里选择了一种非常动态的方法。您真正需要做的唯一选择是使用函数指针还是::std::function对象。 ::std::function对象可以引用任何实现函数调用运算符的东西(例如::std::bind的结果)。函数指针只能引用普通旧函数。

就个人而言,我会调查一个模板化的ObjectiveFunction。部分是因为它调用的函数将在编译时设置,编译器可以更好地优化它们。使用寻根技术,您将会调用它们。因此,在某些情况下,这可能会给您带来显着的加速。

答案 2 :(得分:0)

函数指针可以工作,或者,如果您只是在允许多个实现而不更改调用代码的方法之后,则可以使用继承。

查看函数指针与继承技术的比较here

继承解决方案会像这样;首先创建一个实现所需接口的基类:

class BaseObjectiveFunction
{
    BaseObjectiveFunction();
    virtual ~BaseObjectiveFunction();

    virtual double EvalObjectiveFunction(double);
    virtual double EvalDerivativeFunction(double);
    virtual double EvalSecondDerivativeFunction(double);
}

然后实现一个具有所需功能的继承类:

class LogLikelihood: public BaseObjectiveFunction
{
    public:
        LogLikelihood();
        ~LogLikelihood();

        virtual double EvalObjectiveFunction(double);
        virtual double EvalDerivativeFunction(double);
        virtual double EvalSecondDerivativeFunction(double);

        // Example of a function to pass in some data which the calculations rely on
        bool SetInputData(double* somedata, int dataLen);
}

最后,要调用此代码,您需要创建一个指向基类的指针,并指向您感兴趣的实现(以类似于传递函数指针的方式):

LogLikelihood* pOF1 = new LogLikelihood(); // Create an instantiation of a specific solver
BaseObjectiveFunction* pCaller = pOF1; // Establish a pointer to the interface class and at the specific implementation.

// Now whatever calls the evaluate function can just use the pCaller and doesn't have to worry about the actual implementation.
pCaller->EvalObjectiveFunction(1.5);

这将调用两个底层实现,这是(我认为)你真正想要的。

答案 3 :(得分:0)

#include <stdio.h>

class MyClass
{
public:

  typedef int(MyClass::*FunctionPointer)(int);

  FunctionPointer func;

  void Setup(int selector)
  {
        switch (selector)
        {
              case 1:
              {
                    this->func = (FunctionPointer)&MyClass::Test1;
                    break;
              }
              case 2:
              {
                    this->func = (FunctionPointer)&MyClass::Test2;
                    break;
              }
        }
  }

  void Call()
  {
        (this->*func)(10);
  }

  void Test1(int a)
  {
        printf("test1\n");
  }
  void Test2(int a)
  {
        printf("test2\n");
  }
};

int main()
{
  MyClass *instance = new MyClass();

  instance->Setup(1);
  instance->Call();
  instance->Setup(2);
  instance->Call();

  return 0;
}
相关问题