为何std::function支持以对象引用作为首个参数调用成员函数?
为什么std::function支持用对象引用调用非静态成员函数?
你对非静态成员函数的本质认知是对的:非静态成员函数确实会隐式将对象指针作为首个参数,比如Foo::bar的实际调用逻辑需要接收一个Foo*类型的隐式参数。但std::function之所以支持用对象引用作为首个参数,核心是它内部做了类型适配包装,具体原理如下:
1. 成员函数指针的调用特性
非静态成员函数指针的类型是void (Foo::*)() const(对应示例中的&Foo::bar),这种指针本身就支持两种调用形式:
- 通过对象指针调用:
(obj_ptr->*bar_ptr)() - 通过对象引用调用:
(obj_ref.*bar_ptr)()
C++本身允许这两种调用方式,因为引用本质是对象的别名,对引用取地址就能得到对象指针,两种调用的语义完全等价。
2. std::function的内部适配逻辑
当你把成员函数指针赋值给std::function<void(Foo&)>时,std::function会生成一个内部包装器。这个包装器在被调用时,会自动将传入的Foo&类型参数转换为Foo*(通过&取地址),然后用成员函数指针的指针调用形式执行逻辑。
换句话说,call_bar_by_reference(foo)的内部执行逻辑等价于:
(foo.*&Foo::bar)(); // 或者更直白的等价写法 (&foo)->bar();
3. 标准对可调用对象的适配支持
C++标准规定,std::function的构造和赋值操作,只要传入的可调用对象能被其模板参数指定的调用签名所调用,就允许进行适配。由于成员函数指针既支持通过指针调用,也支持通过引用调用,所以std::function自然支持将成员函数指针适配到这两种参数形式的调用签名上。
示例代码验证
#include <iostream> #include <functional> struct Foo { void bar() const { std::cout << "Foo::bar called " << std::endl; } }; int main() { Foo foo; // version1: pass the object pointer std::function<void(Foo*)> call_bar_by_pointer = &Foo::bar; call_bar_by_pointer(&foo); // or, version2: pass the object reference std::function<void(Foo&)> call_bar_by_reference = &Foo::bar; call_bar_by_reference(foo); return 0; }
内容的提问来源于stack exchange,提问作者QRush
相关产品推荐
相关产品推荐

