【问题标题】:C++ binding callbacks to a classC++ 绑定回调到一个类
【发布时间】:2018-09-15 02:36:00
【问题描述】:

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

所以这行得通:

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;

【问题讨论】:

    标签: c++ functional-programming std-function stdbind


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

      你可以坚持你现在正在做的事情,也可以接受bindEvent中的指向成员函数的指针。

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

      这里要指出的另一件事是,不久前建议使用 lambdas 而不是 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);
         });
      }
      

      【讨论】:

      • 使用 lambdas,哈希映射中的“类型”就变成了一个通用的函数指针,不是吗?:QHash&lt;const QString, QJsonObject(*)(const QString &amp;, const QJsonObject &amp;) &gt; mHandlers;
      • @jramm 该类型仍然是映射定义的std::function。它不完全是一个指向函数的指针,因为它还包含对调用函数的实例的引用。它是一个有状态的函数对象,即使在这种情况下状态永远不会改变。
      • 啊。所以我的哈希可以保持声明为QHash&lt;const QString, std::function&lt;QJsonObject(const QString &amp;, const QJsonObject &amp;)&gt; &gt; mHandlers;
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-11
      • 1970-01-01
      • 2016-02-06
      • 1970-01-01
      • 1970-01-01
      • 2017-05-12
      • 1970-01-01
      相关资源
      最近更新 更多