参考:
https://zh.cppreference.com/w/cpp/utility/functional/bind
https://www.cnblogs.com/xusd-null/p/3698969.html
我们先来看bind的声明
可知bind是一个函数模板,且参数列表是可变的,
取https://www.cnblogs.com/xusd-null/p/3698969.html中的一个例子理解
在使用函数模板bind的时候,
1.会在函数模板中创建一个类(这个类是函数对象),类中有已初始化的成员变量my_handler(函数指针)和123(int类型),
2.在类中重载操作符operator(),传入参数_1与_2,
3.在操作符operator()中,调用函数my_handler并按bind中的顺序传参_2,123,_1,
4.在这个函数模板最后返回这个类创建的函数对象(如下图红框处标记),
之后通过这个返回对象(函数对象)调用重载操作符operator()时,就只用传入_1与_2的参数(此时需注意参数的顺序),因为另一个参数在之前已确定好。
比如我有个函数是用来更新界面的,当我调用时我只知道参数1(界面资源),剩下的要另一个调用者调用时才知道
void NetDownloadDlg::UpdTask(std::shared_ptr<STaskInfoUI> task_info_ui
, double progress, double speed, eTaskState task_state)
此时我就可以通过将目前的已知资源task_info_ui绑定到UpdTask然后生成一个新的函数对象fun_upd_task,供之后的调用者使用
std::shared_ptr<STaskInfoUI> task_info_ui;
//一般不建议这样打乱顺序绑定,影响代码可读性
auto fun_upd_task = std::bind(&NetDownloadDlg::UpdTask,
this,
task_info_ui,
std::placeholders::_2,
std::placeholders::_1,
std::placeholders::_3);
//此时生成了一个新的函数对象,其中有三个成员变量,函数指针UpdTask,
//NetDownloadDlg*对象dlg,shared_ptr<STaskInfoUI>对象task_info_ui
//一个成员函数:重载操作符operator(std::placeholders::_1,std::placeholders::_2,std::placeholders::_3),
//成员函数中会调用dlg->UpdTask(task_info_ui,_2,_1,_3)))
fun_upd_task( 10, 17.8, eTaskFail);//通过函数对象的重载操作符调用UpdTask
//相当于调用UpdTask(task_info_ui,17.8,10,eTaskFail)
另注意:调用指向非静态数据成员指针时,首参数必须是引用或指针。
#include <iostream>
#include <functional>
using namespace std;
typedef void(*fun_rt)(const __int64, int);
void SetCallback(fun_rt callback)
{
int i = 1;
int j = 2;
callback(i,j);
}
//void SetCallback(std::function<void(const __int64, int)> callback)
//{
// int i = 1;
// int j = 2;
// callback(i, j);
//}
void fun_callback_rt(const __int64 handle, int count)
{
cout << handle << endl << count << endl;
}
int main()
{
SetCallback(fun_callback_rt);
SetCallback(std::bind(fun_callback_rt, std::placeholders::_1, std::placeholders::_2));
}
接受bind的类型必须是function,否则会提示错误,
且普通函数指针与bind构造的新的函数对象作为参数是可以重载的。