如何将派生类中的成员函数作为回调传递?

时间:2018-09-01 18:03:34

标签: c++ c++11 callback

我有一个简单的课程X

class X {
public:
    template<typename T>
    void doSomething(T &completion) {
        std::cout << completion(10) << std::endl;
    }
};

以及类AB

class A {
public: 
 // some code
 X* c;
};

class B : public A {
public:
  int test(int x) {
    return x * x;
  }

  void execute() {
   auto lambda = [] (int x) { cout << x * 50 << endl; return x * 100; };
   c->doSomething(lambda); // works
   c->doSomething(&B::test); // does not work
  }
};

我想将doSomething类(或从B派生的任何其他类)的成员方法传递给A方法,但是它不起作用:/

3 个答案:

答案 0 :(得分:5)

  

如何将派生类中的成员函数作为回调传递?

您的问题与B是儿童班无关。您的问题是您没有将非静态成员函数 test()绑定到其实例。

您可以通过using std::bind轻松返回此地址,以返回 functor

c->doSomething(std::bind(&B::test, this, std::placeholders::_1));

别忘了#include <functional>

或使用 lambda 通过将this放在lambda captures中来包装呼叫:

c->doSomething([this](int x){ return this->test(x); });

注意:确保将doSomething()的参数更改为 rvalue引用,以便可以在临时对象和其他对象中正确利用所有这些回调特性。应该看起来像这样:

template<typename T>
void doSomething(T&& completion)

答案 1 :(得分:3)

B::test设为静态方法,它将按书面形式工作:

static int test(int x) {
    return x * x;
}
// ...
c->doSomething(&B::test);

这是因为静态方法不需要隐式实例(this指针)。

如果B::test必须是常规方法,则必须使用捕获的lambda来传递实例,如下所示:

c->doSomething([this] (int x) { return this->test(x); });

注意::要编译此代码,我需要更改您对doSomething的定义,以使&离开T

template<typename T>
void doSomething(T completion) {
    std::cout << completion(10) << std::endl;
}

这可以防止对函数指针类型施加l值或非const约束,从而可以防止编译器创建临时lambda函数。

答案 2 :(得分:1)

您是说c->doSomething([this](int x) { return this->test(x); });吗?