【问题标题】:Reference to member function引用成员函数
【发布时间】:2013-10-30 10:34:06
【问题描述】:

首先我知道这在 C++ 中是不可能的。但我希望有人能说出我的问题的解决方法。我有一个代表数学函数的类:

class myClass:
{
private:
public:
    myClass() {};
    double value(double, double){ /* doing some complicated calculation here */} };
    double integrate { /*calc*/ return integral; };
}

integrate() 中,我想创建一个引用value() 的结构。结构体定义如下:

struct gsl_monte_function_struct {
    double (*f)(double * x_array, size_t dim, void * params);
    size_t dim;
    void * params;
};

(我需要这个结构来从 GSL 调用 Monte-Carlo 集成例程)

如前所述,我知道这在 C++ 中是被禁止的。但是有没有可能将gsl_monte_function_struct 与myClass 的成员函数一起使用?如果myClass 无法自我整合,是否可以在课堂外以value() 为参考调用gsl_monte_function_struct?提前致谢!

【问题讨论】:

    标签: c++ reference struct


    【解决方案1】:

    如果你理解正确,你需要一个指向myClass 的成员函数的指针。您可以通过将成员函数指针声明为:

    double (myClass::*value)(double,double) 
    

    以后可以在实例上调用此函数:

    (instance.*value)(x,y);
    

    或者,您可以使用std::bind 创建一个函数对象,该对象可以作为普通函数调用,而无需在调用std::bind 之后跟踪调用它的实例:

    auto& value = std::bind(myClass::value, instance);
    // ....
    value(x,y);
    

    【讨论】:

    • 应该注意,调用该成员函数指针将需要指向成员的语法,例如->*。在几个问题和答案中有关于 SO 的示例。
    • @WhozCraig 这点很好。这就是为什么我提到 std::bind 以便能够避免它。
    • 感谢您的回答:我试过了:auto d = std::bind(&myClass::value,instance,std::placeholders::_1);。这行得通!但是现在我想做:double (*f)(double y) = d;(这是gsl_monte_function的成员函数)。这失败了!有什么想法吗?
    • 错误是stdbind_example.cpp:29:13: error: no viable conversion from 'std::__1::__bind<double (myClass::*)(double), myClass *&, std::__1::placeholders::__ph<1> &>' to 'double (*)(double)' double (*f)(double y) =d;
    • @user2935834 d 的类型实际上并不是函数指针。它是一个函数对象。您需要将 gsl_monte_function_struct 设为依赖于此类型的模板,或使用成员函数指针 (double (myClass::*value)(double,double) 并将指向实例的指针(类型 myClass*)添加到您的结构中。
    【解决方案2】:

    好的,到目前为止我找到了两个解决方案:

    1)(通用解决方案)使用一个抽象基类,它有一个指向当前实例的静态指针和一个调用派生类函数的静态函数。静态函数可以与函数指针一起使用。

    例子:

    struct gsl_monte{
       double (*f)(double y);
    };
    
    class myBase {
    private:
      static myBase* instance;
    
    public:
      myBase(){};
      static void setInstance(myBase* newOne);
      virtual double value(double x) =0;
      static double callValue(double x);//{return value(x);}
    };
    
    class myClass : public myBase {
       public:
          myClass(){};
          double value(double x) {  return x;  };
    };
    
    myBase* myBase::instance = new myClass();
    double  myBase::callValue(double x){return instance->value(x);}
    void myBase::setInstance(myBase* newOne){instance=newOne;};
    
    double g(double xx) {return xx;};
    
    int main(int argc, char** argv ){
       double x[2]; x[0]=1.3; x[1]=1.3;
       myClass* instance = new myClass();
       myBase::setInstance(instance);
       instance->value(3);
       std::cout << "Test " << myBase::callValue(5) << std::endl;
       gsl_monte T;
       T.f=&myBase::callValue;
       double (*f)(double y, void*) = &myBase::callValue;
    }
    

    2)(针对我的问题的解决方案)幸运的是,所需的函数接受了一个参数指针,我可以使用它来传递当前对象:

    #include <iostream>
    #include <functional>
    using namespace std::placeholders;
    
    struct gsl_monte{
       double (*f)(double y, void*);
    };
    
    class myClass {
       public:
          myClass(){};
          double value(double x) {  return x;  };
    };
    
    double valueTT(double x, void* param) {  return static_cast<myClass*>(param)->value(x);  };
    
    int main(int argc, char** argv ){
       double x[2]; x[0]=1.3; x[1]=1.3;
       myClass* instance = new myClass();
       instance->value(3);
       gsl_monte T;
       T.f=&valueTT;
       double (*f)(double y, void*) = &valueTT;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-06
      • 1970-01-01
      • 2018-11-24
      • 2020-08-09
      • 2021-12-03
      • 1970-01-01
      • 1970-01-01
      • 2018-05-25
      相关资源
      最近更新 更多