函数对象
概念
- 重载函数调用操作符的类,其对象常称为函数对象
- 函数对象使用重载的
()
时,行为类似函数调用,也叫仿函数
本质
函数对象(仿函数)是一个类,不是一个函数
—— 函数对象的使用
特点
- 函数对象在使用时,可以像普通函数那样调用,可以有参数,也可以有返回值
#include <iostream>
using namespace std;
class addTwoNum {
public:
int operator()(int num1, int num2) {
cout << "二数相加结果为:";
return num1 + num2;
}
};
int main() {
// 1. 函数对象在调用时可以有参数和返回值
addTwoNum add; // 创建函数对象
cout << add(1, 3) << endl; // 使用函数对象
// outputs:二数相加结果为:4
system("pause");
return 0;
}
- 函数对象超出普通函数的概念,函数对象可以有自己的状态
#include <iostream>
using namespace std;
class addTwoNum {
public:
addTwoNum() {
this->index = 0;
}
int operator()(int num1, int num2) {
index++;
return num1 + num2;
}
int index;
};
int main() {
// 2. 函数对象也可以有自己的状态
addTwoNum add; // 创建函数对象
// 使用函数对象 -- 并调用三次
add(1, 4);
add(1, 7);
add(1, 8);
// 利用函数对象自己的状态打印出被调用的次数
cout << "add 调用次数:" << add.index << endl; // add 调用次数:3
system("pause");
return 0;
}
- 函数对象可以作为参数传递
#include <iostream>
using namespace std;
class addTwoNum {
public:
int operator()(int num1, int num2) {
return num1 + num2;
}
};
// 函数
void Add(addTwoNum &add, int num1, int num2) {
cout << "二数相加结果为:" << add(num1, num2) << endl;
}
int main() {
// 3. 函数对象可以作为参数传递
addTwoNum add; // 创建函数对象
Add(add, 1, 3); // 二数相加结果为:4
system("pause");
return 0;
}
谓词
概念
- 返回 bool 类型的仿函数称为谓词
- 如果 operator() 接收一个参数,称为一元谓词
- 如果 operator() 接收二个参数,称为二元谓词
—— 一元谓词
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
class greaterFive {
public:
// 一元谓词
bool operator()(int num) {
return num > 5; // 大于 5 则返回 true
}
};
int main() {
vector<int> v;
v.push_back(5);
v.push_back(7);
v.push_back(9);
v.push_back(1);
// 查找容器中有没有大于 5 的数
// 利用算法 find_if -- 返回迭代器指向位置 pos (目前不要求掌握)
// greaterFive() 为匿名函数对象
vector<int>::iterator pos = find_if(v.begin(), v.end(), greaterFive());
if (pos != v.end()) {
cout << "存在大于 5 的数:" << *pos << endl; // 存在大于 5 的数:7
}
else {
cout << "不存在大于 5 的数" << endl;
}
system("pause");
return 0;
}
—— 二元谓词
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
class MyCompare {
public:
// 二元谓词 -- 降序
bool operator()(int num1, int num2) {
return num1 > num2;
}
};
void PrintVector(vector<int> &v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
int main() {
vector<int> v;
v.push_back(5);
v.push_back(7);
v.push_back(9);
v.push_back(1);
// 排序之前
PrintVector(v); // 5 7 9 1
// 算法 sort 将 v 进行排序(默认升序)
sort(v.begin(), v.end(), MyCompare());
// 排序之后
PrintVector(v); // 9 7 5 1
system("pause");
return 0;
}
内建函数对象
概念
STL 内建了一些函数对象
分类
- 算术仿函数
- 关系仿函数
- 逻辑仿函数
用法
- 这些仿函数所产生的对象,用法和一般函数完全相同
- 使用内建函数对象,需要引入头文件
#include <functional>
—— 算术仿函数
功能描述
- 实现四则运算
- 其中 negate 是一元运算,其它都是二元运算
仿函数原型
template<class T> T plus<T>
// 加法仿函数template<class T> T minus<T>
// 减法仿函数template<class T> T multilies<T>
// 乘法仿函数template<class T> T divides<T>
// 除法仿函数template<class T> T modulus<T>
// 取模仿函数template<class T> T negate<T>
// 取反仿函数
#include <iostream>
using namespace std;
#include <functional>
int main() {
// 1. 一元运算
negate<int> n;
cout << n(100) << endl; // -100
// 2. 二元运算
// 加法
plus<int> p;
cout << p(1, 5) << endl; // 6
// 减法
minus<int> m;
cout << m(5, 6) << endl; // -1
// 乘法
multiplies<int> ml;
cout << ml(5, 7) << endl; // 35
// 除法
divides<int> d;
cout << d(9, 4) << endl; // 2
// 取模
modulus<int> md;
cout << md(5, 4) << endl; // 1
system("pause");
return 0;
}
—— 关系仿函数
功能描述
实现关系对比
仿函数原型
template<class T> bool equal_to<T>
// 等于template<class T> bool not_equal<T>
// 不等于template<class T> bool greater<T>
// 大于template<class T> bool greater_equal<T>
// 大于等于template<class T> bool less<T>
// 小于template<class T> bool less_equal<T>
// 小于等于
#include <iostream>
using namespace std;
#include <functional>
#include <vector>
#include <algorithm>
int main() {
// 1. 是否相等
equal_to<int> e;
if (e(1, 1)) {
cout << "二数相等!" << endl; // 二数相等!
}
// 2. 用于排序
vector<int> v;
v.push_back(5);
v.push_back(7);
v.push_back(9);
v.push_back(1);
// 用仿函数实现降序排列
sort(v.begin(), v.end(), greater<int>());
// sort(v.begin(), v.end(), MyCompare());
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " "; // 9 7 5 1
}
cout << endl;
system("pause");
return 0;
}
—— 逻辑仿函数
功能描述
实现逻辑运算
仿函数原型
template<class T> bool logical_and<T>
// 逻辑与template<class T> bool logical_or<T>
// 逻辑或template<class T> bool logical_not<T>
// 逻辑非
#include <iostream>
using namespace std;
#include <functional>
#include <vector>
#include <algorithm>
void PrintVector(vector<bool> &v) {
for (vector<bool>::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(false);
v.push_back(true);
// 1. 逻辑与
logical_and<bool> l_a;
if (l_a(1, 1)) {
cout << "二数的逻辑与运算为 true!" << endl; // 二数的逻辑与运算为 true!
}
PrintVector(v); // 1 0 0 1
// 2. 利用逻辑非,将容器 v 搬运到容器 v1 中,并执行取反操作
vector<bool> v1;
v1.resize(v.size());
transform(v.begin(), v.end(), v1.begin(), logical_not<bool>());
PrintVector(v1); // 0 1 1 0
system("pause");
return 0;
}