关于C++类成员函数绑定到std::function的运行疑问
关于C++类成员函数绑定到std::function的运行疑问
哈哈,这个问题问得好!咱们来拆解一下为什么这段代码看起来不该运行却能正常工作,你的两个疑问其实都和C++成员函数的本质以及std::function的适配规则有关:
先把你的代码贴出来方便参考:
#include <functional> template <class T> void run(std::function<void(T *)> fun, T *obj) { fun(obj); } struct Foo { void bar() {} }; int main() { Foo foo; std::function<void(Foo*)> fun = &Foo::bar; run(fun, &foo); // works }
疑问1:无参数的bar()为什么能匹配接受T*的std::function?
你观察得特别仔细,bar()看起来是无参数的,但C++的非静态成员函数背后都藏着一个隐式的this指针参数。对于Foo::bar()来说,它的实际签名其实是void(Foo*)——这个隐藏的参数就是指向调用该函数的对象的指针。
当你把&Foo::bar赋值给std::function<void(Foo*)>时,std::function内部会自动做适配:它会把传入的Foo*参数当作this指针,去调用bar()成员函数。所以从外部看,std::function要求的是一个接受Foo*的函数,但底层其实是把这个参数映射成了成员函数的this指针,刚好和bar()的调用需求匹配上了。
疑问2:fun只赋值了&Foo::bar,编译器怎么知道要作用在foo对象上?
其实fun并没有提前绑定foo对象,它只是存了Foo::bar这个成员函数的指针而已。当你调用fun(&foo)的时候,才把&foo作为this指针传递给了bar()。换句话说,std::function<void(Foo*)>的作用就是:接受一个Foo*类型的参数,用这个参数作为this来调用存储的成员函数。对象的绑定是在调用fun的那一刻才完成的,不是在初始化fun的时候。
这么一看,这段代码的运行逻辑就通顺啦——run函数把&foo传给fun,fun用这个指针作为this调用foo.bar(),自然就能正常工作了。
备注:内容来源于stack exchange,提问作者Qwe Qwe
相关产品推荐
相关产品推荐

