【问题标题】:How can I pass a member function from a derived class as a callback?如何将派生类的成员函数作为回调传递?
【发布时间】:2018-09-01 18:03:34
【问题描述】:

我有一个简单的课程X

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

还有一个类A和B

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
  }
};

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

【问题讨论】:

  • test 不是函数。它是一个类方法。有很大的不同。模板尝试调用类方法,就好像它是一个函数一样。那是行不通的。您需要一个类实例来调用类方法。您打算调用其方法的类的实例在哪里?
  • @JeJo 是的,我的错 ;) 已编辑

标签: c++ c++11 callback


【解决方案1】:

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

您的问题与 B 是子类无关。您的问题是您没有绑定 非静态成员函数 test() 到它的实例。

你可以很容易地解决这个问题,或者通过using std::bind返回一个函子:

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

别忘了#include &lt;functional&gt;,

或使用 lambda 通过将 this 放入 lambda captures 来包装调用:

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

注意:确保将doSomething() 的参数更改为右值引用,以便它可以在临时对象和其他对象中正确获取所有这些回调优点。应该是这样的:

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

【讨论】:

  • 做到了!谢谢!注意:我必须从 doSomething 方法中删除 &amp;
  • 或者更好的是添加第二个&amp; :) 抱歉,我在您的代码中错过了它。将编辑它。干杯
【解决方案2】:

将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 的定义,以将&amp; 与T 分开:

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

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

【讨论】:

  • 谢谢! Note 部分非常有帮助!它现在按预期工作:)
【解决方案3】:

你的意思是c-&gt;doSomething([this](int x) { return this-&gt;test(x); });?

【讨论】:

  • 是的,就是这样,但应该是 doSomething 而不是 test
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-07
  • 2018-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多