function 和 bind
bind
1. 介绍
bind 可以改变函数的形态,可以将一个函数改变成另一个函数的样式,但只能减少原函数的参数个数,不能增加。
如此处,int add(int, int), 使用bind可以绑定成一个 f 形式,原来的add的两个参数以10,20填入。bind的第一个参数填函数的地址,在普通函数中,函数名就是函数地址,但如果涉及到类的成员函数,就需要 取成员函数的地址,且,成员函数的第一个参数是 this指针,因此,还需要填入一个对象的地址。 (也可以直接传递对象,值传递。)
也就是说,bind的第一个参数是函数地址,后面的参数是该绑定的函数地址的各个参数。
8 #include <functional>
9 #include <iostream>
10 using std::bind;
11 using std::cout;
12 using std::endl;
13
14 int add(int a, int b) {
15 return a + b;
16 }
17
18 int main(int argc, char *argv[]) {
19 auto f = bind(&add, 10, 20);
20 cout << "f() = " << f() << endl;
21 return 0;
22 }
~
2. 占位符
bind可以使用占位符将原函数包装成一个新的可以传参的函数。
如
int add(int a, int b);
using namespace std::placeholders; // 使用占位符的前置条件。
auto f = bind(&add, _1, _3);
f(1,2,3);
add真正调用时,传递的参数是 1号位和3号位,也就是 1 和 3.
这里要注意,当占位符填 n 的时候,则调用的参数个数 >= n。(写再多也没用,就取占位符的那几个。
占位符本身代表的是形参的位置。占位符中的数字,代表的是实参的位置。
bind默认是值传递。如果想要引用传递的话,则需要使用 std::cref
或者 std::ref
其实就是 const reference
。
13
14 void print(int a, int b, int c, int d) {
15 cout << a << " " << b << " " << c << " " << d << endl;
16 }
17
18 int main(int argc, char *argv[]) {
19 int number = 100;
20 using namespace std::placeholders;
21 auto f = bind(&print, _1, _2, std::cref(number), number);
22 number = 3;
23 f(19, 29);
24 return 0;
25 }
3. bind返回值
bind 返回值是function, 暂且当作一个函数的容器。用来填充函数类型的。
函数类型就是函数返回值 + 函数参数。(函数参数:参数类型、参数个数、参数顺序)
auto f = bind(...);
function<int()> = bind(...);
function
function< 函数类型 >
函数类型一般是 int() , int表示返回值类型,()表示参数类型。
-
类的数据成员可以就地初始化。
-
bind可以绑定到类的数据成员上。
-
bind对象可以地址传递,也可以值传递。(地址传递时,使用前不能销毁该对象。)
1. 回调函数
function 可以用来注册回调函数。如:
using CallBack function<int()>;
CallBack _displayCallBack;
右值引用在作为函数参数的时候,是左值,给function 的指针赋值的时候使用 std::move
将其更改为右值。
也就是说,使用 function
定义一个函数指针,然后 bind
传入一个实参,实现 function
和 bind
的结合。
此时,不但可以以面向对象的形式完成多态, 还可以以基于对象的形式完成多态。
- 面向对象:继承 + 虚函数(纯虚函数)
- 基于对象:
std::bind + std::function
基于对象更灵活,面向对象更紧密。