You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么std::function绑定成员函数时可使用两种不同可调用类型?

struct Foo {
    Foo(int num) : num_(num) {}
    void print_add(int i) const { std::cout << num_+i << '\n'; }
    int num_;
};

int main ()
{
    function<void(const Foo*, int)> func = &Foo::print_add;
    function<void(const Foo&, int)> func2 = &Foo::print_add;
    Foo f(1), f2(2);
    func(&f, 2);
    func2(f2, 3);
    return 0;
}

问题解答

这一现象的核心是C++标准为std::function定义的**INVOKE调用协议**,专门兼容了成员函数调用时对象参数的多种传入形式。

  • 你对非静态成员函数的调用规则认知是正确的:Foo::print_add作为const成员函数,调用时确实需要隐式传入类型为const Foo*的this指针。
  • std::function包装可调用对象时,不会要求参数和可调用对象的原生参数完全硬匹配,只会判断参数是否满足INVOKE规则的合法调用要求。对于指向成员函数的指针,INVOKE规则允许第一个参数为以下任意一种类型:
    1. 成员所属类的匹配指针:此时直接将该指针作为this参数传入成员函数,对应代码中func的用法,func(&f, 2)等价于(&f)->print_add(2),完全符合语法要求。
    2. 成员所属类的匹配左值引用:此时编译器会自动取引用对应对象的地址作为this指针传入,对应代码中func2的用法,func2(f2, 3)等价于(&f2)->print_add(3),不会出现类型不匹配的问题。
    3. 额外补充:std::shared_ptr<Foo>、std::unique_ptr<Foo>这类智能指针也可以作为第一个参数传入,INVOKE规则会自动处理得到合法的this指针。
  • 这种设计是std::function的核心特性之一:抹平不同可调用对象的调用形式差异,对外提供统一的调用接口,上层使用者不需要关心底层封装的是普通函数、成员函数还是自定义仿函数,只要按std::function声明的签名传参即可。

内容的提问来源于stack exchange,提问作者codesavesworld

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 12:15:00