函数对象包装器是对函数的封装,为函数对象提供一个容器,一个封装。C++中现有的可调用实体的一种类型安全的包装(相对来说,函数指针的调用不是类型安全的),换句话说,函数对象包装器就是函数的容器。
当我们有了函数的容器之后便能够更加方便的将函数、函数指针作为对象进行处理。直接调用函数包装器,传值,就可以调用函数。
函数对象包装器支持4种函数的封装
1.普通函数
2.匿名函数
3.类的成员函数
4.仿函数(重载了运算符的函数)
=========================================
1.普通函数的对象包装器
- include "stdafx.h"
- #include <algorithm>
- #include <iostream>
- #include <vector>
- #include <funtional>
-
- using namespace std;
-
-
- int printf1(int value1,int value2)
- {
-
- int ret = value1+value2;
- printf("普通函数的类对象包装器");
- printf("ret = %d",ret);
- return value;
- }
-
- int main()
- {
-
- printf1(3,5);
- std::function<int(int)> function1 = printf1;
-
- function1(3,6);
-
- return 0;
-
- }
===============================================================
2.匿名函数的对象包装器
Lambda的本质是一个特殊的,匿名的类类型。它是一个带有operator()的类,即仿函数。仿函数opratoer就是使一个类的使用看上去像一个函数,其实现就是类中实现一个operator(),这个类有了类似函数的行为,就是一个仿函数类了。
仿函数是一个重载了 operator() 运算符、能行使函数功能的类,这个类也称为函数对象类,这个类的对象就是函数对象。函数对象本质上是一个对象,但其使用形式看起来和函数调用一样
Lambda表达式具体形式如下:
[capture](parameters)->return-type{body}
最简单的匿名函数是[](){},它没有参数也没有返回值。在匿名函数中,[]里面用来捕获函数外部的变量,而()里面就是匿名函数的参数,{}里面就是函数的执行代码。
- auto + 名字 =[]()->返回值{};
- 具体介绍:
- 1.[ ] 中括号表示函数对象的构造函数中是否接收外部变量。
- [&] 表示使用引用的方式获取外部变量
- [=] 表示使用值的拷贝的方式获取外部变量。
-
- 2.() 这个小括号是就函数对象中的小括号符后面的参数列表。
-
- 3.->返回值,需要就放,不需要就不放。根据自己需要,任君选择。
-
- 4.{...} 就是函数对象的小括号运算符的函数体。
Lambda表达式实现例子
- class Addnum{
- public:
-
- AddNum(int x):num_(num){};
- //int addNum(int x) const {
- //return num_ + x ;
- //}
-
- int operator(){int x} const{
- return num_ + x;
- }
- }
-
- int main()
- {
- //operator
- auto add_num = AddNum(10);
- //auto x = add_num.addNum(5);
- auto x = add_num(5);
- std::cout<<"x:"<<x<<std::endl;
-
- //lambda
- //替代掉Addnum类
- auto add_num2 = [lamada_num =10](int x){return lamada_num +10};
-
- auto lamada_x = add_num_2(5);
- std::cout<<"lamada x:"<<lamada_x <<std::endl;
-
- }
========================================================
lamada函数的对象包装器
- #include <iostream>
- #include <vector>
- #include <algorithm>
- #include <functional>
- using namespace std;
-
- int printf1(int value1,int value2)
- {
-
- int ret = value1+value2;
- printf("普通函数的类对象包装器");
- printf("ret = %d",ret);
- return value;
- }
-
-
- class Printf_source {
- public:
- Printf_source() {} //构造函数
-
- /*****************************************
- //operator()仿函数替代了My_Printf_source函数
- int My_Printf_source(int n1,int n2) {
- int ret = n1+n2;
- printf("普通函数的类对象包装器");
- printf("ret = %d",ret);
- return ret;
- }
- *********************************************/
- //仿函数 ———————————————————代替My_Printf_source函数
- int operator()(int n1,int n2) {
- int ret = n1+n2;
- printf("普通函数的类对象包装器");
- printf("ret = %d",ret);
- return ret;
- }
-
- };
-
-
- int main()
- {
- //函数对象包装器:
- //为了函数提供了一种容器(封装),存放在对象或者变量中
- printf1(3,5); //打印出8
-
- //普通函数的封装
- //<int >返回值;(int)参数列表;
- std::function<int(int)> function1 = printf1;
- function1(3,6); //打印出9
-
- //匿名函数
- function<int(int)>function2 = [](int n1,int n2)->int {
- int ret = value1+value2;
- printf("类对象包装器");
- printf("ret = %d",ret);
- return ret;
- };
- function2(7,8); //打印出15
-
- return 0;
-
- }
-
========================================================
再看个下面的例子,将对象包装器做为参数传递的情况
- #include <iostream>
- #include<functional> //提供function模板类
-
-
- //传统C函数
- int c_function(int a, int b)
- {
- return a + b;
- }
-
-
- //函数对象
- class Functor
- {
- public:
- int operator()(int a, int b)
- {
- return a + b;
- }
- };
-
- //用函数指针做参数
- typedef int (*pfun)(int, int);
-
- //函数的第一个参数只能接收函数指针
- void show1(pfun f, int a, int b)
- {
- std::cout << f(a, b) << std::endl;
- }
-
- //用function<...>做参数
- //函数第一个参数可以接收任何返回值为int,参数为int,int的可调用类型
- void show2(std::function<int(int, int)> f, int a, int b)
- {
- std::cout << f(a, b) << std::endl;
- }
- int main()
- {
- show1(c_function, 3, 6); //输出9
- //show1(Functor(), 3, 3); //编译错误,因为Functor()不能转换为函数指针
- show2(c_function, 3, 5); //输出8
- show2(Functor(), 3, 3); //输出6
- system("pause");
- }
==================================================
对象包装器的赋值操作
成员函数指针是一种指向类的非静态成员函数的指针。它的类型声明需要加上类名
&不是必须的;&是必须的。非静态成员函数的第一个参数是this指针(它是隐藏的),因此在包装时需要指明第一个形参的类型为类的类型。- #include <iostream>
- #include<functional>
-
- //测试用函数
- int Minus(int a, int b)
- {
- return a - b;
- }
-
- //测试用类
- class A
- {
- public:
- int operator()(int a, int b)
- {
- return a * b;
- }
- void show(int a, int b)//普通成员函数
- {
- std::cout << a << " " << b << std::endl;
- }
- static void staticshow(int a, int b)//静态成员函数
- {
- std::cout << a << " " << b << std::endl;
- }
- };
- int main()
- {
- using namespace std::placeholders;
- A a;
-
- //(1)function<>赋值类成员函数
- //第一种方法
- // 非静态成员函数包含一个隐藏的this指针,所以形参需要多定义一个类型A
- std::function<void(A&, int, int)> f1(&A::show);
- f1(a, 3, 6); //输出:3 6
-
- //第二种方法
- // 非静态成员函数包含一个隐藏的this指针,所以形参需要多定义一个类型A
- std::function<int(A, int, int)> f1 = &A::show;
- f1(A(), 3, 6);
-
- //*********************************************************************************
-
- //(2)function<>赋值类静态成员函数
- //第一种方法
- std::function<void(int, int)> f2(&A::staticshow);
- f2(6, 6);//输出:6 6
-
- //第二种方法
- std::function<int(int,int)> f2 = A::staticshow;
-
- //*********************************************************************************
-
- //(3)function<>赋值bind
- //如果函数有多个参数,可以绑定部分参数,其他的参数在调用的时候指定
- std::function<int(int)> f3 = std::bind(Minus, 10, _1);
- std::cout << f3(1) << std::endl; //输出:9
-
- //*********************************************************************************
-
- //(4)function<>赋值Lambda表达式
- std::function<int(int, int)> f4 = [](int a, int b) {return a + b; };
- std::cout << f4(3, 9) << std::endl; //输出:12
-
- //*********************************************************************************
-
- //(5)function<>赋值函数对象
- //第一种方法
- std::function<int(int, int)> f5 = A();
- std::cout << f5(6, 6) << std::endl; //输出:36
-
- //第二种方法
- std::function<int(int, int)> f5 = a;
- std::cout << f5(6, 6) << std::endl; //输出:36
- system("pause");
-
-
- }