函数对象
函数对象
1.什么是函数对象
1.类中重载了(),这个类实例化的对象叫函数对象(仿函数);
2.一元仿函数是operator()中只需要一个参数。二元仿函数是operator()中需要二个参数
2.有什么用
1.做为算法的策略
void test()
{
vector<int> v;
v.push_back(8);
v.push_back(1);
v.push_back(6);
v.push_back(3);
v.push_back(7);
//内建函数对象(仿函数)
sort(v.begin(), v.end(), greater<int>());
for_each(v.begin(), v.end(), [](int val){cout << val << " "; });
//[](int val){cout << val << " "; }//匿名函数
}
3.函数对象和普通函数的区别
1.函数对象可以有自己的状态
2.普通函数没有类型,函数对象有类型
3.函数对象比普通函数执行效率有可能更高(成员函数自动申请为内联函数)
4.谓词
1.谓词是指普通函数或重载的operator()返回值是bool类型的函数对象(仿函数)。
2.谓词可以作为一个判断式
3.接受一个参数,那么叫做一元谓词,如果接受两个参数,那么叫做二元谓词
struct GreaterThanFive{
bool operator()(int v){
return v >5;
}
};
//一元谓词
void test01(){
vector<int> v;
for(int i =0; i <10;i++){
v.push_back(i);
}
vector<int>::iterator ret = find_if(v.begin(), v.end(), GreaterThanFive());
if(ret == v.end()){
cout <<"没有找到!"<< endl;
}
else{
cout <<"找到:"<<*ret << endl;
}
}
//二元谓词
struct MyCompare{
bool operator()(int v1,int v2){
return v1 > v2;
}
};
void test02(){
vector<int> v;
srand((unsignedint)time(NULL));
for(int i =0; i <10; i++){
v.push_back(rand()%100);
}
for(vector<int>::iterator it = v.begin(); it != v.end(); it ++){
cout <<*it <<" ";
}
cout << endl;
//排序算法
sort(v.begin(), v.end(), MyCompare());
for(vector<int>::iterator it = v.begin(); it != v.end(); it++){
cout <<*it <<" ";
}
cout << endl;
}
5.内建函数对象
1.使用内建的函数对象要加入头文件#include
/*
template<class T> bool equal_to<T>//等于
template<class T> bool not_equal_to<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>//小于等于
*/
void test01(){
equal_to<int> MyEqual;
if(MyEqual(10,20)){
cout <<"相等!"<< endl;
}
else{
cout <<"不相等!"<< endl;
}
函数对象适配
1.什么是函数对象适配:当函数对象的参数不够用,那么可以用适配器来配置函数对象。
2.函数适配器:bind1st,bind2nd,将二元函数对象配置为一元函数对象
//第一步:继承binary_function<参数1,参数2,返回类型>
struct Myfunc:public binary_function<int,int,void>
{
void operator()(int v1,int v2)const //第二步:加上const成为常函数,参数变2个
{
//cout << v1 << " " << endl;
cout << v1 + v2 << endl;//第三步:实现函数体
}
};
//需求:打印时,每个元素加100然后打印出来
void test()
{
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(50);
//for_each(v.begin(), v.end(), Myfunc());
//第四步:用bind2nd来绑定函数对象
for_each(v.begin(), v.end(), bind2nd(Myfunc(),100));
}
3.bind1st和bind2nd的区别
bind1st把100绑定给第一个参数,bind2nd把100绑定给第二个参数
4.函数对象适配器 not1 not2 取反
1.not1和not2的区别:not1针对一元函数对象,not2针对二元函数对象
2.使用not1和not2
//第一步:继承
struct MyNotfunc:public unary_function<int,bool>
{
bool operator()(int v)const //第二步:变为常函数
{
return v >= 20;
}
};
//not1 和not2
void myPrint(int val)
{
cout << val << " ";
}
void test02()
{
vector<int> v;
v.push_back(10);
v.push_back(50);
v.push_back(30);
v.push_back(40);
v.push_back(50);
//find_if()
/*
_InIt _Find_if(_InIt _First, _InIt _Last, _Pr _Pred)
{ // find first satisfying _Pred
for (; _First != _Last; ++_First)
if (_Pred(*_First))
break;
return (_First);
}
*/
//第三步:适配
vector<int>::iterator it=find_if(v.begin(), v.end(), not1(MyNotfunc()));
if (it == v.end())
{
cout << "查找失败" << endl;
}
else
{
cout << "查找成功=" << *it << endl;
}
//not2的使用
//less 二元函数对象
vector<int> v2;
v2.push_back(10);
v2.push_back(50);
v2.push_back(30);
v2.push_back(40);
v2.push_back(50);
//release模式下可以
sort(v2.begin(), v2.end(),not2(less<int>()));
for_each(v2.begin(), v2.end(), myPrint);
}
5.普通函数进行适配
//普通函数进行适配 ptr_fun
//第一步:把一个参数变为二个参数
void myprint2(int val,int val2)
{
cout << val+val2<< " ";
}
void test03()
{
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(50);
//第二步:把普通函数变为函数对象 ptr_fun
for_each(v.begin(), v.end(), bind2nd(ptr_fun(myprint2),100));
}
6.成员函数适配
1.mem_fun : 如果存储的是对象指针,需要使用mem_fun
2.mem_fun_ref : 如果存储的是对象,需要使用mem_fun_ref
class Maker
{
public:
Maker(string name,int age)
{
this->name = name;
this->age = age;
}
//成员函数
void MyprintMaker() //成员函数时无参 不可作为for_each的一元函数对象
{
cout << "Name:" << this->name << " Age:" << this->age << endl;
}
public:
string name;
int age;
};
//void MyprintMaker(Maker m) //因为调用的是函数指针所以不用写 ()
//{
// cout << "Name:" << m.name << " Age:" << m.age << endl;
//}
/* C++中的 `for_each` 函数
在C++中,标准模板库(STL)提供了 `for_each` 函数,用于对容器中的每个元素执行指定操作。该函数的第三个参数通常被称为“unary function”,因为它应该接受容器中的每个元素作为参数。
当传递一个普通函数给 `for_each` 函数时,C++编译器会进行函数模板参数推断。这意味着编译器会根据函数的签名推断出相应的函数对象类型,从而将普通函数隐式地转换为函数对象,使得它可以接受容器中的每个元素作为参数。
因此,即使你传递的是一个普通函数,它也能够满足 `for_each` 需要的函数对象的形式,从而正确地处理容器中的元素。*/
void test04()
{
vector<Maker> v;
v.push_back(Maker("aaa", 10));
v.push_back(Maker("bbb", 20));
v.push_back(Maker("ccc", 30));
//当容器存储的是对象,用mem_fun_ref适配他的成员函数
/*
在 mem_fun_ref 中,你需要传递一个成员函数指针作为参数,以便函数能够在容器的每个元素上调用该成员函数。虽然在C++中,成员函数的名称本身可以作为函数指针,但在这种情况下,需要明确地获取成员函数的地址,以符合 mem_fun_ref 函数的参数要求。
*/
for_each(v.begin(), v.end(), mem_fun_ref(&Maker::MyprintMaker)); //第三个参数需要具有一个参数的函数指针 or 函数对象 or lambda表达式
cout << "-------------" << endl;
vector<Maker*> vp;
vp.push_back(new Maker("aaa", 10));
vp.push_back(new Maker("bbb", 20));
vp.push_back(new Maker("ccc", 30));
//当容器存储的是对象指针,用mem_fun适配他的成员函数
for_each(vp.begin(), vp.end(), mem_fun(&Maker::MyprintMaker));
}

浙公网安备 33010602011771号