文章目录
- 包装器
- function
- 包装器可以包装可调用对象
- 其他使用示例
🎖 博主的CSDN主页:Ryan.Alaskan Malamute
📜 博主的代码仓库主页 [ Gitee ]:@ryanala [GitHub]: Ryan-Ala
包装器
function
使用 function包装器需要包含头文件 functional
#include<functional>
function是一种函数包装器,也叫做适配器。它可以对可调用对象进行包装,本质就是一个类模板
function类模板的原型如下:
template <class T> function; // undefined
template <class Ret, class... Args> //第一个Ref 是返回值类型,后面是可调用对象的参数
class function<Ret(Args...)>;
- 第一个Ref 是返回值类型
- … Args 是可调用对象的参数
详细解释:
- 该代码定义了一个模板类函数,该类接受一个或多个类型参数。
- 第一行是一个不完整的声明,因为没有指定函数类型参数的具体类型,因此它是未定义的。
- 第二行定义了一个模板类 function,它有一个类型参数Ret和一个变长模板参数Args,表示返回值类型和函数参数类型
- 这个模板类的具体实现是针对函数类型 Ret(Args…)的。也就是说,这个模板类可以用来存储任意类型为Ret(Args…)的函数指针、函数对象等。
- function包装器可以对可调用对象进行包装,包括函数指针(函数名)、仿函数(函数对象)、lambda表达式、类的成员函数等
包装器可以包装可调用对象
function解决可调用对象的类型问题,把可调用对象统一包装起来,存放到vector,map中去。
function主要可以包装下面三大类:
-
函数指针
class A {static func_1(int x,int y){} //包装成员函数需要加类域func_2(int x,int y){} }
- 静态成员函数:取出静态成员函数的地址时,需要通过类名,但&不是必须的;
- 非静态成员函数:取出非静态成员函数的地址时,需要通过类名,但&是必须的。非静态成员函数的第一个参数是this指针(它是隐藏的),因此在包装时需要指明第一个形参的类型为类的类型。
-
包装类内静态函数
类的静态函数没有 this 指针,只要正确的取地址包装即可,当然也可以不取地址
&
,直接加上类域也是可以的function<int(int,int)> f1 = A::func_1
class A {static func_1(int x,int y){} func_2(int x,int y){} }function<int(int,int)> f1 = &A::func_1; // 需要域名加取地址 同时该成员函数必须是静态的 f1(1,2);
-
包装类内非静态函数
-
方式1:传入一个对象的指针 >>
function<int(A* , int , int )>
非静态成员函数含有 this 指针,此时需要传一个对象的指针,在调用时内部就会使用该指针去调用函数。
注意:不可以使用 临时对象 因为临时对象时又指无法对临时对象取地址
class A {static func_1(int x,int y){} func_2(int x,int y){} }int main() {function<int(A* ,int,int)> f2 = &A::func_2; //非静态成员函数有一个隐含的this指针A new_A; f2(&A,1,2); //底层是用传过去的指针调用成员函数//注意: 这里不能使用临时对象,临时对象是右值,无法取地址f2(A(),1,2); //错误的 }
-
方式2:传入对象 >>
function<int(A ,int , int )>
或者直接传入一个对象,那么底层会使用这个对象去调用该函数
class A {static func_1(int x,int y){} func_2(int x,int y){} }int main() {function<int(A ,int,int)> f2 = &A::func_2;f2(A(),1,2); //正确的//底层使用对象去调用这个 函数指针 }
-
bind 绑定(非 socket 编程的 bind ,这两个是老婆和老婆饼的关系)
使用bind对函数进行处理将某些参数写死,后续调用时也就不需要传入对象或者对象的指针了 ,对于bind后续还会进行讲解。
using namespace std::placeholders; // 绑定对象 function<int(A ,int,int)> f2 = bind(&A::func_2,A(),placeholders::_1,placeholders::_2); f2(1,2); //使用绑定将某些参数写死//绑定指针 A a; function<int(A* ,int,int)> f2 = bind(&A::func_2,&a,placeholders::_1,placeholders::_2); f2(1,2); //使用绑定将某些参数写死
-
-
-
仿函数
function包装器也可以用来包装仿函数,不过初始化时要加上括号
Swap()
,因为这里必须是可调用对象示例:
struct Swap {void operator()(int& r1, int& r2){ // .......} };function<void(int&, int&)> f2 = Swap(); f2(x, y);
-
lambda
function包装器也可以包装Lambda表达式,这种方式代码较为简短,是一种非常常用的方式
auto swaplambda = [](int& r1, int& r2) {int tmp = r1;r1 = r2;r2 = tmp;};function<void(int&, int&)> f3 = swaplambda; f3(x, y);
其他使用示例
int main()
{map<string, function<void(int&, int&)>> cmdOP = {{"函数指针", swap_func},{"仿函数", Swap()},{"lambda", swaplambda},};cmdOP["函数指针"](x, y);cout << x << " " << y << endl << endl;cmdOP["仿函数"](x, y);cout << x << " " << y << endl << endl;cmdOP["lambda"](x, y);cout << x << " " << y << endl << endl;
}