函数对象
1 概念
- 函数对象是重载函数调用操作符的类的对象,也叫仿函数
- 函数对象可以有参数和返回值,可以作为参数传递
以下代码是一个仿函数实例,可以通过重载小括号实现两个数的相加。当然,不仅可以实现加法功能,四则运算,排序,输出打印功能均可实现。
//一个仿函数实例
class FunctorAdd {
public:
int operator()(int v1, int v2) {
this->count += 1;//每次调用count+1
return v1 + v2;//实际实现了括号的两个数相加
}
int count;//记录运行加法的次数
};
int main()
{
FunctorAdd add;
cout << add(10, 10) << endl;
}
上述代码还可以发现,如果在仿函数类中设置一个能够记录状态的变量(本例中的count),我们可以根据需求记录函数对象的状态。
仿函数的写法非常的灵活,也可以作为参数进行传递。如下面这段代码。doAdd()函数实现的功能即为两个数的相加。运行结果为35.
int doAdd(FunctorAdd func, int v1, int v2) {
return func(v1, v2);
}
int main()
{
FunctorAdd func;
cout << doAdd(func,12, 23);
}
2 谓词
- 返回类型为bool的仿函数称为谓词
- operator()接受一个参数称为一元谓词
//一元谓词
class FunctorGF{
public:
int operator()(int val) {
return val > 5;
}
};
int main()
{
vector<int>v = { 1,34,2,3,43,34,23,43,2,34,343,423,42,4 };
vector<int>::iterator iter;
// FunctorGF()匿名函数对象,查找有没有大于5的数字
iter=find_if(v.begin(), v.end(), FunctorGF());
if (iter == v.end()) {
cout << "not find" << endl;
}
else
cout << "at least a number is greater than 5" << endl;
}
- operator()接受两个参数称为二元谓词
二元谓词最经典的案例就是排序了。STL中很多容器都可以加入自定义的排序规则。不妨写一个set容器的降序排列的实现方法作为二元谓词的案例。
//二元谓词
class FunctorCmp{
public:
int operator()(int v1,int v2)const {
return v1 > v2;//实现降序排列
}
};
int main()
{
set<int,FunctorCmp>s = { 1,34,2,3,43,34,23,43,2,34,343,423,42,4 };
set<int>::iterator iter;
for (iter = s.begin();iter != s.end();iter++)
cout << *iter << " ";
}
输出为:
423 343 43 42 34 23 4 3 2 1
3 内建函数对象
STL内建了一些函数对象,整体分为关系仿函数、逻辑仿函数和算术仿函数三类。这些仿函数所产生的对象用法和一般函数完全相同,但使用时需要引入头文件
#include <function>
3.1 关系仿函数
template bool equal_to //等于
template bool not_ equal_to //不等于
template bool greater //大于
template bool greater_equal //大于等于
template bool less //小于
template bool less_equal //小于等于
int main()
{
vector<int> test;
for (int i = 0;i < 10;i++) {
test.push_back(i * 3);//0 3 6 9 12 15 18 21 24 27
}
sort(test.begin(), test.end(), greater<int>());//把它整成降序
cout << "descending order:";
for (int i = 0;i < 10;i++) {
cout << test[i] << " ";
}
cout << endl;
sort(test.begin(), test.end(), less<int>());//再把它整成升序
cout << "increasing order:";
for (int i = 0;i < 10;i++) {
cout << test[i] << " ";
}
}
输出结果
descending order:27 24 21 18 15 12 9 6 3 0
increasing order:0 3 6 9 12 15 18 21 24 27
3.2 逻辑仿函数
实现与或非的逻辑运算
template bool logical_and //逻辑与
template bool logical_or //逻辑或
template bool logical_not //逻辑非
int main()
{
vector<bool> v1 = { true, false, true, false, true };
vector<bool> v2 = { true, true, false, false, true };
vector<bool> res;
res.resize(v1.size());
cout << "raw data v1: ";
for (int i = 0;i < 5;i++) {
cout << v1[i] << " ";
}
cout << endl;
cout << "raw data v2: ";
for (int i = 0;i < 5;i++) {
cout << v2[i] << " ";
}
cout << endl;
cout << "logical not data: ";
cout << endl;
//用transform函数实现数据转化,存储在res容器中
transform(v1.begin(), v1.end(), res.begin(), logical_not<bool>());
for (int i = 0;i < 5;i++) {
cout << " not " << v1[i] << " = " << res[i] << endl;
}
cout << "logical and data: ";
cout << endl;
transform(v1.begin(), v1.end(), v2.begin(), res.begin(), logical_and<bool>());
for (int i = 0;i < 5;i++) {
cout <<v1[i] << " and " << v2[i] << " = " << res[i] << endl;
}
cout << endl;
cout << "logical or data: ";
cout << endl;
transform(v1.begin(), v1.end(), v2.begin(), res.begin(), logical_or<bool>());
for (int i = 0;i < 5;i++) {
cout << v1[i] << " or " << v2[i] << " = " <<res[i] << endl;
}
}
输出结果:
raw data v1: 1 0 1 0 1
raw data v2: 1 1 0 0 1
logical not data:
not 1 = 0
not 0 = 1
not 1 = 0
not 0 = 1
not 1 = 0
logical and data:
1 and 1 = 1
0 and 1 = 0
1 and 0 = 0
0 and 0 = 0
1 and 1 = 1logical or data:
1 or 1 = 1
0 or 1 = 1
1 or 0 = 1
0 or 0 = 0
1 or 1 = 1
3.3 算术仿函数
template T plus //加法仿函数
template T minus //减法仿函数
template T multiplies //乘法仿函数
template T divides //除法仿函数
template T negate //取反仿函数
class FunctorCmp{
public:
int operator()(int v1,int v2)const {
return v1 > v2;//实现降序排列
}
};
int main()
{
plus<int>plus;
minus<int>min;
multiplies<int>mul;
divides<int>div;
negate<int>neg;
cout << "plus functor: 13+14=" << plus(13, 14) << endl;
cout << "minus functor: 13-14=" << min(13, 14) << endl;
cout << "multiplies functor: 13*14=" << mul(13, 14) << endl;
cout << "divides functor: 28/14=" << div(28, 14) << endl;
cout << "negate functor: -20=" << neg(20) << endl;
}
输出结果:
plus functor: 13+14=27
minus functor: 13-14=-1
multiplies functor: 13*14=182
divides functor: 28/14=2
negate functor: -20=-20