C++ 绑定回调到 class

C++ binding callbacks to a class

我正在 class 中注册到散列映射的回调以处理各种 'events',所以我使用 std::function 将它们存储在散列映射中 我希望将回调绑定到 class 以便它们可以访问一些常用方法,因此我使用 std::bind 来完成此操作。 我不明白的是为什么第一个示例有效,但是当我尝试重构对 bindEvent 函数的 std::bind 调用时,编译失败。

所以这有效:

void MyClass::bindEvent(const QString event, std::function<QJsonObject(const QString &, const QJsonObject &)> handler)
{
   mHandlers.insert(event.toLower(), handler);
}


void MyClass::registerAll()
{

   this->bindEvent(QStringLiteral("do_something"), std::bind(&MyClass::doSomething, this, _1, _2));
   this->bindEvent(QStringLiteral("do_something_else"), std::bind(&MyClass::doSomethingElse, this, _1, _2));
}

这失败了:

void MyClass::bindEvent(const QString event, std::function<QJsonObject(const QString &, const QJsonObject &)> handler)
{
   mHandlers.insert(event.toLower(), std::bind(handler, this, _1, _2));
}


void MyClass::registerAll()
{

   this->bindEvent(QStringLiteral("do_something"), &MyClass::doSomething);
   this->bindEvent(QStringLiteral("do_something_else"), &MyClass::doSomethingElse);
}

错误信息:

../src/MyClass.cpp: In member function ‘virtual bool MyClass::registerAll()’:
../src/MyClass.cpp:124:388: error: no matching function for call to ‘MyClass::bindEvent(QString, QJsonObject (MyClass::*)(const QString&, const QJsonObject&))’
    this->bindEvent(QStringLiteral("do_something"), &MyClass::doSomething);
                                                                                                                                                                                                                                                                                                                                                                                                    ^
../src/MyClass.cpp:124:388: note: candidate is:
../src/MyClass.cpp:109:6: note: void MyClass::bindEvent(QString, std::function<QJsonObject(const QString&, const QJsonObject&)>)
 void MyClass::bindEvent(const QString event, std::function<QJsonObject(const QString &, const QJsonObject &)> handler)
      ^
../src/MyClass.cpp:109:6: note:   no known conversion for argument 2 from ‘QJsonObject (MyClass::*)(const QString&, const QJsonObject&)’ to ‘std::function<QJsonObject(const QString&, const QJsonObject&)>’

散列本身声明为

QHash<const QString, std::function<QJsonObject(const QString &, const QJsonObject &)> > mHandlers;

我认为问题可能在于它不是一个函数,而是一个包含在 class 或命名空间中的函数。我认为你需要在签名中指定它。

或者使用 lambda 表达式可能会导致解决方法。由于您没有提供最小的工作示例,因此我无能为力。创建时,您可能会发现问题所在或让人们发现您的错误。

第二次尝试失败,因为需要在对象上调用成员函数。当您传递 pointer-to-member-function 时,没有对象可以调用该函数,因此无法将其转换为 std::function.

你可以坚持现在做的事情,也可以在bindEvent中接受一个pointer-to-member-function。

void MyClass::bindEvent(const QString event, QJsonObject (MyClass::*handler)(const QString &, const QJsonObject &))
{
   mHandlers.insert(event.toLower(), std::bind(handler, this, _1, _2));
}

这里要指出的另一件事是,不久前就建议使用 lambda 而不是 std::bind。据我了解,它为编译器提供了更好的机会来优化代码。

我个人也觉得它更具可读性。

void MyClass::bindEvent(const QString event, QJsonObject (MyClass::*handler)(const QString &, const QJsonObject &))
{
   mHandlers.insert(event.toLower(), [&, handler](const QString& s, const QJsonObject& o){
      this->*handler(s, o);
   });
}