普通函数可直接赋值给std::function,类成员函数必须绑定对象;普通函数要求签名完全匹配,重载时需static_cast;成员函数需用lambda或std::bind处理this指针;std::function可能为空,调用前须检查。

普通函数直接赋值就能用;类成员函数必须显式绑定对象,否则编译失败。
普通函数包装:类型匹配后直接赋值
只要函数签名(返回值 + 参数列表)和 std::function 模板参数完全一致,就能直接赋值。不需要 std::bind,也不需要 lambda 中转。
- 声明时必须写全签名,比如
std::function<int int></int>不能写成std::function<int></int> - 函数名本身是左值,可直接赋给
std::function变量,本质是隐式转换为函数指针 - 如果函数重载了,编译器可能无法推导目标,需显式转型:
static_cast<int>(add)</int>
示例:
int add(int a, int b) { return a + b; }
std::function<int(int, int)> f = add; // ✅ 合法
f(2, 3); // 返回 5
类成员函数包装:必须解决 this 指针问题
成员函数隐含 this 参数,所以它的原始类型不是 int(int, int),而是类似 int (Calculator::*)(int, int) —— 这和 std::function<int int></int> 类型不兼容,直接赋值会编译报错。
立即学习“C++免费学习笔记(深入)”;
- 用 lambda 捕获对象引用或指针最直观,推荐用于局部绑定:
[&obj](int a, int b) { return obj.add(a, b); } - 用
std::bind也可行,但语法略冗长,且需引入std::placeholders;_1和_2位置要和目标参数顺序严格对应 - 如果想保留“未绑定对象”的灵活性,可声明为
std::function<int int></int>,然后传入实例调用,但这样每次都要多传一个对象参数
示例(lambda 方式):
struct Calculator {
int add(int a, int b) const { return a + b; }
};
Calculator calc;
std::function<int(int, int)> f = [&calc](int a, int b) { return calc.add(a, b); };
f(4, 5); // 返回 9
容易踩的坑:空函数调用和类型擦除开销
std::function 是类型擦除容器,内部可能堆分配(尤其对大 lambda),且每次调用有间接跳转开销。更关键的是:它可能为空。
- 未初始化、赋值为
nullptr或 move 后的std::function调用会抛std::bad_function_call - 务必在调用前检查:
if (f) f(1, 2);,而不是依赖异常处理 - 静态成员函数没有
this,可像普通函数一样直接赋值:std::function<int int> f = &Calculator::subtract;</int>
真正麻烦的从来不是怎么写,而是忘记检查是否为空,或者误以为成员函数能像普通函数一样直赋 —— 这两点在调试时往往卡很久。


















