函数对象(仿函数)
基本概念
重载函数调用操作符的类,其对象称为函数对象
函数对象使用重载的()时,行为类似函数调用,因此也被称为仿函数
本质
函数对象(仿函数)是一个类,而不是一个函数!!!
函数对象(仿函数)的使用
特点:
1、函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
2、函数对象超出普通函数的概念,函数对象可以有自己的状态
3、函数对象可以作为参数传递(因为函数对象本身就是一个实例化的对象,因此可以作为参数)
eg:
#include <iostream>
using namespace std;
#include<string>
//1、1、函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
class functionAdd
{
public:int operator()(int a,int b)//重载函数调用操作符,用于实现加法运算{return a + b;}
};
//2、函数对象超出普通函数的概念,函数对象可以有自己的状态
class funcPrint {
public:void operator()(string test)//重载函数调用操作符,用于打印传入的字符{cout << test << endl;count++;//每次调用重载()都会使count++}int count=0;//统计调用此函数对象的次数
};
void test01()
{funcPrint fp;//实例化函数对象//需求:统计调用了多少次此仿函数fp("hello world");fp("hello world");fp("hello world");fp("hello world");fp("hello world");cout << "此函数对象调用的次数为:" << fp.count << endl;
}
//3、函数对象可以作为参数传递(因为函数对象本身就是一个实例化的对象,因此可以作为参数)
void doPrint(funcPrint &fp,string test)
{fp(test);//相当于间接调用函数对象进行打印
}
int main()
{functionAdd f;//实例化函数对象cout<<f(10, 10)<<endl;//f(10, 10)书写方式与函数调用及其相似test01();funcPrint fp;//实例化对象doPrint(fp,"hello C++");return 0;
}
注:参数列表中加了const和没加const是两种不同的参数列表,即若仿函数实现的参数列表中无const修饰,但实现函数调用时却用了const修饰,则编译器会找不到与参数列表和对象匹配的函数
eg:
class funcPrint {
public:
void operator()(string test)//重载函数调用操作符,用于打印传入的字符
{
cout << test << endl;
}
};void doPrint(const funcPrint &fp,string test)//错误
{
fp(test);
}void doPrint(funcPrint &fp,string test)//正确
{
fp(test);//相当于间接调用函数对象进行打印
}
谓词
基本概念
返回bool类型的仿函数就称为谓词
如果operator()接受一个参数,就叫做一元谓词
如果operator()接受两个参数,就叫做二元谓词
一元谓词
eg:
需求:找出容器中大于5的数
#include <iostream>
using namespace std;
#include<string>
#include<vector>
class GreaterFive {//一元谓词
public:bool operator()(int val){return val > 5;//当val大于5时返回true,即满足需求}
};
int main()
{vector<int>v;for (int i = 0; i < 10; i++){v.push_back(i);}//GreaterFive()是一个匿名对象,find_if第一、二、三个参数分别填需遍历容器的起始位置、终止位置以及实例化的函数对象vector<int>::iterator it;it=find_if(v.begin(), v.end(),GreaterFive() );//若找到,则find_if会返回指向该元素的迭代器,否则返回v.end()if (it == v.end()){cout << "容器中无比5大的元素" << endl;}else{cout << "容器中第一个比5大的元素为: " << *it << endl;}return 0;
}
二元谓词
eg:
#include <iostream>
using namespace std;
#include<vector>
#include<algorithm>
bool compare(int left,int right)
{return left > right;
}
class Greater {
public:bool operator()(int left, int right){return left > right;}
};
int main()
{vector<int>v;for (int i = 0; i < 10; i++)//升序插入{v.push_back(i);}//用改变sort的排序规则,使其变为降序排列---可以使用函数实现,当然也可以用二元谓词实现sort(v.begin(), v.end(), Greater());//Greater()是一个匿名的函数对象for (vector<int>::iterator it = v.begin(); it != v.end(); it++)//遍历动态数组{cout << *it << " ";}cout << endl;return 0;
}
内建函数对象
内建函数对象的意义
STL中提供了一些仿函数模板对数据进行相应的处理,处理数据时仅需调用相应的仿函数就可以,大大减小了无意义的工作,为写代码提供了便利。
分类:
内建的函数对象分为算数仿函数、关系仿函数、逻辑仿函数
用法:
1、这些仿函数所产生的对象,用法和一般函数完全相同。
2、使用内建函数对象,需要包含头文件即#include<functional>
算术仿函数
功能描述:
1、实现四则运算
2、其中negate是一元运算(即只有一个操作数),其他都是二元运算
eg:
#include <iostream>
using namespace std;
#include<functional>int main()
{//其他二元运算同理plus<int>p;//对象实例化--创建一个int类型的一个函数对象int ret=p(10, 20);//将10与20相加,函数返回结果用ret接收cout << ret << endl;negate<int>n;//注意实例化对象时需要知名模板参数的类型ret=n(50);//对50取反操作cout << ret << endl;return 0;
}
关系防函数
功能描述:
通过内置的仿函数,实现关系对比。
eg:
#include <iostream>
using namespace std;
#include<functional>
#include<vector>
#include<algorithm>
class Greater {//此仿函数即为greater的实现原理bool operator()(int left, int right){return left > right;}
};
int main()
{vector<int>v;for (int i = 0; i < 10; i++){v.push_back(i);}//greater<int>()---greater是STL提供的内置仿函数模板,<int>用于指代模板参数类型,greater<int>()即用于创建一个匿名对象用于实现降序排列sort(v.begin(), v.end(), greater<int>());//实现容器降序排列for (vector<int>::iterator it = v.begin(); it != v.end(); it++)//编列动态数组{cout << *it << " ";}cout << endl;return 0;
}
注:1、sort函数之所以默认是升序排列,就是因为sort函数第三个参数默认为less(即小于仿函数)
2、greater在实际应用中使用较多,其他关系仿函数的应用与greater类似,理解掌握即可
逻辑仿函数
用于实现逻辑运算
逻辑仿函数实际应用较少,了解即可