这个回调有什么问题?

时间:2016-10-27 15:39:39

标签: c++ function callback

这是我的code

#include <iostream>
#include <stdio.h>

using namespace std;

typedef void (*CallbackType)(double); 

class LFO
{
private:

public:
    CallbackType target;

    inline void Process() {
        double value = 1.3;
        target(value);
    }
};

class ExternalObject
{
private:

public:
    double mTest = 1.0;

    ExternalObject() {

    }
    ~ExternalObject() {

    }

    inline void PrintValue(double value) {
        cout << "passed: " << value << endl;
    }
};

int main ()
{
    ExternalObject eo;
    LFO lfo;

    lfo.target = eo.PrintValue;
    lfo.Process();
}

我想在LFO的Process中执行ExternalObject的回调PrintValue。但似乎我不能以这种方式通过lfo.target?我哪里错了? (对不起,我是C ++的新手;在JavaScript中我就是这样做的。)

1 个答案:

答案 0 :(得分:1)

Foo的定义如下:

CallbackType

这基本上是一个typedef void (*CallbackType)(double); 并且不返回任何内容的函数(double)。

当你像这样指定void时:

eo.PrintValue

您的类型不匹配:因为lfo.target = eo.PrintValue; PrintValue类的非静态成员函数。非静态成员函数有一个&#34;隐藏&#34; 附加参数,它是指向类实例的ExternalObject指针。

有点像this的实际声明:

PrintValue

您可以修复void ExternalObject::PrintValue(ExternalOject* this, double value) PrintValue static方法 ExternalObject,因为static方法不具备this {1}}指针参数。 E.g:

class ExternalObject {
 public:
  // Note: you don't need "inline" here
  static void PrintValue(double value) {
     ...
  }

P.S。通常,当您有回调时,C ++中的常见模式是在回调中提供额外的void*参数。这可用于为回调函数提供一些上下文,包括传递前面提到的this指针(因此静态成员函数回调可以使用this指针来调用非静态方法)。

P.P.S。该回调样式通常可在C接口API中找到。在C ++中,您可能需要考虑std::function(例如std::function<void(double)>)。

您也可以考虑使用带有重载operator()的类作为回调的设计(所谓的&#34;仿函数&#34; ,或&#34;函数对象& #34; ),例如:

#include <functional>  // for std::function
#include <iostream>

class LFO {
public:
    std::function<void(double)> Target;

    void Process() {
        double value = 1.3;
        Target(value);
    }
};

class ValuePrinter {
public:
    void operator()(double value) const {
        std::cout << "passed: " << value << '\n';
    }
};

int main() {
    LFO lfo;
    lfo.Target = ValuePrinter();
    lfo.Process();
}

作为另一种选择,您可以使用 std::bind double参数的占位符,例如在main内:

ExternalObject eo;
LFO lfo;

using namespace std::placeholders;
lfo.Target = std::bind(&ExternalObject::PrintValue, &eo, _1);
lfo.Process();

可编辑的代码:

#include <functional>
#include <iostream>

class LFO {
public:
    std::function<void(double)> Target;

    void Process() {
        double value = 1.3;
        Target(value);
    }
};

class ExternalObject {
public:
    double mTest = 1.0;

    ExternalObject() = default;

    void PrintValue(double value) {
        std::cout << "passed: " << value << '\n';
    }
};

int main() {
    ExternalObject eo;
    LFO lfo;

    using namespace std::placeholders;
    lfo.Target = std::bind(&ExternalObject::PrintValue, &eo, _1);
    lfo.Process();
}