为何std::bind绑定不匹配的回调能编译?如何修复参数错误?
std::bind与std::function匹配问题解答
示例代码
#include <iostream> #include <memory> #include <vector> #include <functional> class Bar { public: void bind_function(std::function<void(int)> callback){ m_callbacks.push_back(callback); } void invoke() { for(auto& c : m_callbacks){ c(12345); } } private: std::vector<std::function<void(int)>> m_callbacks; }; class Foo{ public: void register_foo(){ m_msg.bind_function(std::bind(&Foo::callback_foo, this)); } void callback_foo(/*int a*/){ std::cout << "callback foo invoked!!!!" << std::endl; } void run() { m_msg.invoke(); } private: Bar m_msg; }; int main(){ Foo foo; foo.register_foo(); foo.run(); return 0; }
问题解答
为何无参的
callback_foo能匹配std::function<void(int)>并编译通过?
这是因为std::bind返回的函数对象具备参数兼容性:当调用该函数对象时,若传入的参数数量多于目标函数(callback_foo)所需,多余的参数会被直接忽略。而std::function<void(int)>仅要求其存储的可调用对象能接受一个int参数并执行——不管这个对象实际会不会使用该参数。因此无参的callback_foo被bind包装后,生成的函数对象可以接受int参数(只是不使用),完全符合std::function<void(int)>的要求,所以能编译通过。如何修复回调改为带int参数后的编译错误?
编译错误的核心原因是:当callback_foo带int参数时,std::bind(&Foo::callback_foo, this)没有为成员函数的参数预留位置,bind无法确定调用时传入的int参数该传递到哪里。解决方法是添加占位符std::placeholders::_1,明确表示调用时传入的第一个参数要传递给callback_foo的int形参。
修改后的代码如下:
// 修改register_foo方法 void register_foo(){ m_msg.bind_function(std::bind(&Foo::callback_foo, this, std::placeholders::_1)); } // 恢复callback_foo的参数 void callback_foo(int a){ std::cout << "callback foo invoked!!!!, param: " << a << std::endl; }
这样bind生成的函数对象就能正确接收invoke传入的int参数,并传递给callback_foo,编译错误即可消除。
内容的提问来源于stack exchange,提问作者waas1919
相关产品推荐
相关产品推荐

