C++11风格的回调

C++11 styled callbacks?

本文关键字:回调 风格 C++11      更新时间:2023-10-16

我在类中有一个void函数。在旧的C++中,我会将类名作为参数来创建一个静态函数,并拥有自己的类,该类使用静态void函数+一个void*来轻松调用它。

然而,这感觉很老套。它也没有模板化,感觉我可以做得更多。创建myclassVar.voidReturnVoidParamFunc 回调的更现代的方法是什么

使用std::function和lambdas(或std::bind())存储可调用文件:

#include <functional>
#include <iostream>

class Test
{
public:
      void blah() { std::cout << "BLAH!" << std::endl; }
};
class Bim
{
public:
      void operator()(){ std::cout << "BIM!" << std::endl; }
};
void boum() { std::cout << "BOUM!" << std::endl; }

int main()
{
    // store the member function of an object:
    Test test;  
    std::function< void() > callback = std::bind( &Test::blah, test );
    callback();
    // store a callable object (by copy)
    callback = Bim{};
    callback();
    // store the address of a static function
    callback = &boum;
    callback();
    // store a copy of a lambda (that is a callable object)
    callback = [&]{ test.blah(); }; // often clearer -and not more expensive- than std::bind()
    callback();
}      

结果:

废话!

BIM!

BOUM!

废话!

编译并运行:http://ideone.com/T6wVp

std::function可以用作任何可复制的对象,所以可以将其作为回调存储在某个位置,比如对象的成员中。这也意味着您可以自由地将其放入标准容器中,如std::vector< std::function< void () > >

还要注意,等效的boost::function和boost::bind已经存在多年了。

有关使用Lambda和向量向C++11回调传递参数的示例,请参阅http://ideone.com/tcBCeO或以下:

class Test
{
public:
      Test (int testType) : m_testType(testType) {};
      void blah() { std::cout << "BLAH! " << m_testType << std::endl; }
      void blahWithParmeter(std::string p) { std::cout << "BLAH1! Parameter=" << p << std::endl; }
      void blahWithParmeter2(std::string p) { std::cout << "BLAH2! Parameter=" << p << std::endl; }
      private:
         int m_testType;
};
class Bim
{
public:
      void operator()(){ std::cout << "BIM!" << std::endl; }
};
void boum() { std::cout << "BOUM!" << std::endl; }

int main()
{
    // store the member function of an object:
    Test test(7);  
    //std::function< void() > callback = std::bind( &Test::blah, test );
    std::function< void() > callback = std::bind( &Test::blah, test );
    callback();
    // store a callable object (by copy)
    callback = Bim{};
    callback();
    // store the address of a static function
    callback = &boum;
    callback();
    // store a copy of a lambda (that is a callable object)
    callback = [&]{ test.blah(); }; // might be clearer than calling std::bind()
    callback();
    // example of callback with parameter using a vector
    typedef std::function<void(std::string&)> TstringCallback;
    std::vector <TstringCallback> callbackListStringParms;
    callbackListStringParms.push_back( [&] (const std::string& tag) {     test.blahWithParmeter(tag); }); 
    callbackListStringParms.push_back( [&] (const std::string& tag) { test.blahWithParmeter2(tag); }); 
    std::string parm1 = "parm1";
    std::string parm2 = "parm2";
    int i = 0;
    for (auto cb : callbackListStringParms ) 
    {
        ++i;
        if (i == 1)
            cb(parm1);
        else
            cb(parm2);
    }
}