文章目录
- 1 函数对象
- 1.1 函数对象的概念
- 1.2 函数对象使用
- 2 谓词
- 2.1 谓词的概念
- 2.2 一元谓词
- 2.3 二元谓词
- 3 内建函数对象
- 3.1 内建函数对象的基本概念
- 3.2 算术仿函数
- 3.3 关系仿函数
- 3.4 逻辑仿函数
1 函数对象
1.1 函数对象的概念
函数对象/仿函数:重载函数调用操作符operator()
的类的对象。使用重载的()
时,行为类似函数调用,亦称仿函数。
本质:函数对象/仿函数本质是一个类,而不是函数。
1.2 函数对象使用
调用方式:函数对象名(参数)
特点:
(1)函数对象使用时,类似于普通函数的调用, 可包含参数和返回值;
(2)函数对象可具有自己的内部状态(本质是类对象,可包含成员属性);
(3)函数对象可作为函数的参数传递,且仍支持函数对象/仿函数的调用方式。
注:函数对象/仿函数的使用方式很灵活,可包含不同类型的参数列表和返回值。
示例1:函数对象使用时,类似于普通函数的调用, 可包含参数和返回值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include <iostream> using namespace std; /* 函数对象使用时,类似于普通函数的调用, 可包含参数和返回值 */ class MyAdd { public: //重载函数调用运算符() int operator()(int a, int b) { return a + b; } }; int main() { //创建函数对象 MyAdd myAdd; //调用函数对象 cout << myAdd(1, 2) << endl; //3 return 0; }
示例2:函数对象可具有自己的内部状态;函数对象可作为函数的参数传递。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45#include <iostream> using namespace std; /* 函数对象可具有自己的内部状态(本质是类对象,可包含成员属性) */ class Printer { public: //成员变量记录函数对象的内部状态 int count; Printer() { //初始化成员变量(即初始化函数对象的内部状态) this->count = 0; } //重载函数调用运算符() void operator() (string text){ cout << text << endl; count++; //更新函数对象的内部状态 } }; /* 函数对象可作为函数的参数传递 */ void func(Printer &printer, string text) { //作为函数的参数传递时,仍支持函数对象/仿函数的调用方式 printer(text); } int main() { Printer printer; //调用函数对象 printer("Hello Cpp!"); printer("Hello Cpp!"); printer("Hello Cpp!"); //查看函数对象的内部状态 cout << "函数对象的调用次数:" << printer.count << endl; //3 //函数对象作为函数的参数传递 func(printer, "Cheer Up!"); //Cheer Up! return 0; }
2 谓词
2.1 谓词的概念
谓词:返回值类型为bool类型
的仿函数。
一元谓词
:operator()
的形参列表只包含一个参数。
二元谓词
:operator()
的形参列表包含两个参数。
注1:只有返回值类型为bool类型的仿函数,称为谓词。返回值类型为其它类型的仿函数,不是谓词。
注2:谓词对应STL源码中的class _Pr
类。
当STL内置函数需要_Pr _Pred
(谓词)类型的参数时,可传入:
①函数对象,即函数对象类名 对象名;
②匿名函数对象,即函数对象类名()
③回调函数名
④匿名函数(lambda表达式),即[](..){..}
仿函数/函数对象-实现自定义排序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16//函数对象/仿函数 class MyCompare { public: //重载函数调用运算符() bool operator()(int val1, int val2) { //return val1 < val2; //升序排序 return val1 > val2; //降序排序 } }; //使用仿函数/函数对象,按自定义规则排序 MyCompare mc; sort(vec.begin(), vec.end(), mc); //函数对象mc sort(vec.begin(), vec.end(), MyCompare()); //匿名函数对象MyCompare()
回调函数-实现自定义排序:
1
2
3
4
5
6
7
8
9//回调函数 bool myCompare(int val1, int val2){ //return val1 < val2; //升序排序 return val1 > val2; //降序排序 } //使用回调函数,按自定义规则排序 sort(vec.begin(), vec.end(), myCompare);
匿名函数(lambda表达式)-实现自定义排序:
1
2
3//使用匿名函数(lambda表达式),按自定义规则排序 sort(vec.begin(), vec.end(), [](int val1, int val2) {return val1 > val2;});
2.2 一元谓词
示例:查找大于5的元素(一元谓词、回调函数)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51#include <iostream> using namespace std; #include <vector> #include <algorithm> //仿函数:大于5的值 class GreaterThanFive { public: //重载函数调用运算符 bool operator()(int val) { return val > 5; //大于5时返回true } }; //回调函数:大于5的值 bool greaterthanfive(int val) { return val > 5; //大于5时返回true } int main() { vector<int> v; v.push_back(3); v.push_back(2); v.push_back(0); v.push_back(5); v.push_back(9); //iterator find_if(iterator begin, iterator end, _Pr _Pred) //_Pr类型:可传入函数对象或回调函数名 //1.传入匿名函数对象 vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterThanFive()); //2.传入函数对象 //GreaterThanFive gt; //vector<int>::iterator it = find_if(v.begin(), v.end(), gt); //3.传入回调函数名 //vector<int>::iterator it = find_if(v.begin(), v.end(), greaterthanfive); //回调函数 if (it != v.end()) { cout << "查找到大于5的元素:" << *it << endl; } else { cout << "未查找到大于5的元素" << endl; } return 0; }
2.3 二元谓词
示例:自定义排序(二元谓词、回调函数)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61#include <iostream> using namespace std; #include <vector> #include <algorithm> //打印vector元素的函数模板 template<typename T> void printVector(vector<T>& v) { //for循环遍历 for (typename vector<T>::iterator it = v.begin(); it != v.end(); it++) { cout << (*it) << " "; } cout << endl; } //回调函数-实现自定义排序 bool myCompare(int val1, int val2) { return val1 > val2; //降序排序 //return val1 < val2; //升序排序 } //仿函数-实现自定义排序 class MyCompare { public: //重载函数调用运算符 bool operator()(int val1, int val2) { return val1 > val2; //降序排序 //return val1 < val2; //升序排序 } }; int main() { vector<int> v; v.push_back(6); v.push_back(3); v.push_back(9); v.push_back(1); v.push_back(7); cout << "排序前:" << endl; printVector<int>(v); //6 3 9 1 7 //1.回调函数实现自定义排序: //cout << "回调函数实现自定义排序:" << endl; //sort(v.begin(), v.end(), myCompare); //回调函数名 //printVector<int>(v); //9 7 6 3 1 //2.函数对象/仿函数实现自定义排序: //cout << "函数对象/仿函数实现自定义排序:" << endl; //sort(v.begin(), v.end(), MyCompare()); //匿名函数对象 //printVector<int>(v); //9 7 6 3 1 //3.匿名函数(lambda表达式)实现自定义排序: //cout << "匿名函数(lambda表达式)实现自定义排序:" << endl; sort(v.begin(), v.end(), [](int val1, int val2) {return val1 > val2;}); //匿名函数(lambda表达式) printVector<int>(v); //9 7 6 3 1 return 0; }
3 内建函数对象
3.1 内建函数对象的基本概念
STL提供了内建函数对象,底层源码重载函数调用运算符operator()
,主要分为3类。
(1)算术仿函数
:实现四则运算;
(2)关系仿函数
:实现关系比较,如大于小于、相等不相等。
(3)逻辑仿函数
:实现逻辑运算,如与或非运算。
使用方法:
内建函数对象(仿函数的对象),使用方法与一般函数完全相同,需包含头文件 #include<functional>
。
3.2 算术仿函数
算术仿函数:实现四则运算。取反仿函数negate
是一元运算,其它均为二元运算。
仿函数原型:
template<class T> T plus<T>
:加法仿函数
template<class T> T minus<T>
:减法仿函数
template<class T> T multiplies<T>
:乘法仿函数
template<class T> T divides<T>
:除法仿函数
template<class T> T modulus<T>
:取模仿函数
template<class T> T negate<T>
:取反仿函数
示例:算术仿函数的使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <iostream> using namespace std; #include <functional> //内建函数对象的头文件 int main() { /* 一元运算 */ //取反运算 negate<int> neg; cout << neg(5) << endl; //-5 /* 二元运算 */ //加法运算 plus<double> p; cout << p(3.33, 6.66) << endl; //9.99 return 0; }
3.3 关系仿函数
关系仿函数:实现关系比较。
仿函数原型:
template<class T> bool equal_to<T>
:等于。
template<class T> bool not_equal_to<T>
:不等于。
template<class T> bool greater<T>
:大于,匿名对象greater<T>()
可用于降序排序。
template<class T> bool greater_equal<T>
:大于等于。
template<class T> bool less<T>
:小于,匿名对象less<T>()
默认用于升序排序。
template<class T> bool less_equal<T>
:小于等于。
示例:内建函数对象实现降序排序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47#include <iostream> using namespace std; #include <vector> #include <algorithm> #include <functional> //内建函数对象的头文件 //打印vector元素的函数模板 template<typename T> void printVector(vector<T>& v) { //for循环遍历 for (typename vector<T>::iterator it = v.begin(); it != v.end(); it++) { cout << (*it) << " "; } cout << endl; } //自定义仿函数 class MyCompare { public: bool operator()(int v1, int v2) { //降序排序 return v1 > v2; } }; int main() { vector<int> v; v.push_back(6); v.push_back(3); v.push_back(9); v.push_back(1); v.push_back(7); printVector<int>(v); //6 3 9 1 7 //自定义仿函数实现降序排序 //sort(v.begin(), v.end(), MyCompare()); //printVector<int>(v); //9 7 6 3 1 //内建函数对象实现降序排序:greater<int>() sort(v.begin(), v.end(), greater<int>()); printVector<int>(v); //9 7 6 3 1 return 0; }
3.4 逻辑仿函数
逻辑仿函数:实现逻辑运算。
注:逻辑仿函数的实际应用较少,了解即可。
仿函数原型:
template<class T> bool logical_and<T>
:逻辑与
template<class T> bool logical_or<T>
:逻辑或
template<class T> bool logical_not<T>
:逻辑非
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38#include <iostream> using namespace std; #include <vector> #include <functional> #include <algorithm> //打印vector元素的函数模板 template<typename T> void printVector(vector<T>& v) { //for循环遍历 for (typename vector<T>::iterator it = v.begin(); it != v.end(); it++) { cout << (*it) << " "; } cout << endl; } int main(){ vector<bool> v; v.push_back(true); v.push_back(false); v.push_back(true); v.push_back(false); printVector<bool>(v); //1 0 1 0 /* 逻辑非仿函数 */ vector<bool> vec; //指定vec的容器大小为v vec.resize(v.size()); //将容器v的元素搬运至vec中,且执行逻辑非运算 transform(v.begin(), v.end(), vec.begin(), logical_not<bool>()); printVector<bool>(vec); //0 1 0 1 return 0; }
最后
以上就是落后服饰最近收集整理的关于C++ STL(十):函数对象/仿函数(函数对象、谓词、内建函数对象)1 函数对象2 谓词3 内建函数对象的全部内容,更多相关C++内容请搜索靠谱客的其他文章。
发表评论 取消回复