您的位置:首页 >C++11包装器function和bind示例详解
发布于2026-05-20 阅读(0)
扫一扫,手机访问
在C++的现代编程实践中,我们常常会遇到一个挑战:如何统一地处理不同类型的可调用对象?比如,你有一个普通函数、一个仿函数、一个lambda表达式,甚至是一个类的成员函数。它们功能相似,但类型各异,直接放在一起管理会非常麻烦。这时候,std::function 就该登场了。
简单来说,std::function 是一个类模板,它的核心使命就是“统一类型”。它能把各种形态的可调用对象包装起来,让它们穿上统一的“外衣”,从而实现多态调用。你可以把它想象成一个万能的函数指针,但功能要强大得多。
它的基本格式是 std::function<返回值类型(参数类型列表)>。这个模板实例化出来的对象,就可以用来存储(或者说“包装”)一个目标可调用对象。如果这个 std::function 对象内部没有存储任何目标,那它就是“空”的,调用一个空的 std::function 会抛出 std::bad_function_call 异常。
来看看它能包装些什么:
int add(int a, int b) { return a + b; } // 普通函数
struct Mul {
int operator()(int a, int b) { return a * b; }
}; // 仿函数
class MyClass{
public:
static int s_add(int a,int b){
return a+b;
}
int add(int a,int b){
return a+b;
}
};
int main() {
function f; // 创建一个空的 std::function
f = add; // 包装普通函数
f = Mul(); // 包装仿函数对象
f = [](int a, int b) { return a - b; }; // 包装 lambda 表达式
f = &MyClass::s_add; // 包装静态成员函数,需要取地址并指明类域
// 包装普通成员函数有点特殊,因为需要传递 this 指针。
// 在 std::function 的模板参数中,需要显式写出接收对象的类型。
function c_f; // 按值传递对象
function p_f; // 按指针传递对象
c_f = &MyClass::add;
p_f = &MyClass::add;
// 调用时,需要将对应的对象实例传进去
MyClass mc;
cout << c_f(mc, 1, 1) << endl; // 传递对象
cout << p_f(&mc, 1, 1) << endl; // 传递对象地址
function empty_func;
// empty_func(); // 错误!不能调用空的目标
return 0;
}
可以看到,无论是哪种形式,最终我们都能通过统一的 f 对象来调用,这就是它的威力所在。
如果说 std::function 解决了“类型统一”的问题,那么 std::bind 则擅长解决“参数适配”的问题。它也是一个函数模板,可以看作是一个可调用对象的“加工厂”。
bind 接收一个原始的可调用对象 fn 和一个参数列表 arg_list,然后返回一个新的可调用对象。这个新对象的神奇之处在于,你可以重新安排、固定甚至减少原始调用所需要的参数。它的常见用法是:auto newFunc = bind(func, arg_list);
这里的关键在于理解 arg_list。它并不是直接传递的参数值列表,而是定义了新函数 newFunc 的参数如何映射到原函数 func 的参数上。占位符 _1, _2, _3...(位于 std::placeholders 命名空间)代表 newFunc 的第1、2、3...个参数。如果不使用占位符,而是直接写入一个值,那么这个参数就被“固定”住了。
void func(int a, int b)
{
cout << a << " " << b << endl;
}
int main()
{
using namespace std::placeholders; // 使用占位符
// 1. 调整参数顺序:将 newfunc1 的第2个参数给 func 的第1个位置,第1个参数给 func 的第2个位置
auto newfunc1 = bind(func, _2, _1);
newfunc1(10, 20); // 实际调用 func(20, 10),输出:20 10
// 2. 固定部分参数:将 func 的第一个参数固定为 100
auto newfunc2 = bind(func, 100, _1);
newfunc2(200); // 实际调用 func(100, 200),输出:100 200
// 3. 减少参数数量:将 func 的两个参数全部固定
auto newfunc3 = bind(func, 66, 88);
newfunc3(); // 实际调用 func(66, 88),输出:66 88
}
通过 bind,我们可以非常灵活地生成适配不同接口的新函数对象,再结合 std::function 进行统一管理,这在设计回调机制、事件系统时尤其有用。两者联手,为C++的函数式编程风格提供了强大的基础设施。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8