如何在C++类方法内部使用std::bind绑定自身成员函数
类方法内部绑定自身带参函数的问题解决
我需要在类方法内部绑定带指定参数的自身函数,用于调度回调——现有一个基于std::chrono时间标识到std::function<void(void)>的multimap调度器,希望方法执行后,调度自身在未来再次调用,因此要创建自身的std::bind对象存入multimap。但始终写不对语法,比如以下代码:
#include <functional> #include <iostream> class x { public: void testBind(char y); }; void x::testBind(char y) { std::cout<<"Blah! " << y << "\n"; auto boundItself = std::bind(&x::testBind, &x, std::placeholders::_1); boundItself('h'); }
编译时会报错:
error C2275: 'x': expected an expression instead of a type
问题原因
你出错的核心是std::bind的第二个参数传错了:在类成员函数内部,要获取当前实例的指针,必须用this,而不是&x——x是类的类型名,&x代表的是类型的地址,不是具体实例的地址,这不符合std::bind绑定成员函数的要求(绑定成员函数时,第二个参数必须是该类的实例指针/引用)。
对比cppreference上的示例:
struct Foo { void print_sum(int n1, int n2) { std::cout << n1+n2 << '\n'; } int data = 10; }; int main() { using namespace std::placeholders; Foo foo; auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1); f3(5); return 0; }
这个示例能运行,是因为它在main函数里传入了具体实例的地址&foo;而你在成员函数内部,当前实例的指针就是this,直接用它即可。
修正后的代码
基础绑定(保留参数占位符)
先修正基础的绑定逻辑,让boundItself能正常调用:
#include <functional> #include <iostream> class x { public: void testBind(char y); }; void x::testBind(char y) { std::cout<<"Blah! " << y << "\n"; // 用this代替&x,获取当前实例的指针 auto boundItself = std::bind(&x::testBind, this, std::placeholders::_1); boundItself('h'); } // 测试调用 int main() { x obj; obj.testBind('a'); return 0; }
适配调度需求(绑定为无参std::function<void(void)>)
如果要适配你的调度器(需要存入std::function<void(void)>类型的回调),可以固定参数,生成无参的可调用对象:
#include <functional> #include <iostream> #include <map> #include <chrono> class x { public: void testBind(char y) { std::cout<<"Blah! " << y << "\n"; // 绑定当前实例+固定参数,得到无参的可调用对象 auto boundSelf = std::bind(&x::testBind, this, 'h'); // 存入调度multimap:key为调度时间,value为无参回调 std::multimap<std::chrono::steady_clock::time_point, std::function<void(void)>> scheduler; auto nextInvokeTime = std::chrono::steady_clock::now() + std::chrono::seconds(1); scheduler.emplace(nextInvokeTime, boundSelf); // 模拟调度执行(实际场景中由调度器在时间到达后触发) if (!scheduler.empty()) { scheduler.begin()->second(); } } }; int main() { x obj; obj.testBind('a'); return 0; }
这样绑定后的boundSelf就是一个无需传入参数的可调用对象,完全符合std::function<void(void)>的要求,可以直接存入你的调度multimap中。
内容的提问来源于stack exchange,提问作者DSiegmeyer
相关产品推荐
相关产品推荐

