C++11 风格的回调?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12338695/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:11:10  来源:igfitidea点击:

C++11 styled callbacks?

c++c++11

提问by Klaim

I have a void function inside of a class. In old C++ i'd make a function static taking the class name as a parameter and had my own class which took a static void function + a void* for me to easily call it.

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

However that feels old school. It also isn't templated which feels like i could be doing more. What is a more modern way of creating callbacks to myclassVar.voidReturnVoidParamFunc

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

回答by Klaim

Use std::functionand lambdas (or std::bind())to store callables:

使用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();
}      

Result:

结果:

BLAH!

BIM!

BOUM!

BLAH!

哎呀!

BIM!

砰!

哎呀!

Compiles and run: http://ideone.com/T6wVp

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

std::functioncan be used as any copyiable object, so feel free to store it somewhere as a callback, like in object's member. It also means that you can freely put it in standard containers, like std::vector< std::function< void () > >.

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

Also note that equivalent boost::function and boost::bindhave been available for years.

另请注意,等效的boost::function 和 boost::bind已经存在多年。

回答by LeslieM

For an example of passing in parameters to a C++ 11 callback using Lambda's and a vector, see http://ideone.com/tcBCeOor below:

有关使用 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);

    }
}