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

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











