加载中...

函数对象

函数对象

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));
}
posted @ 2024-02-21 21:21  江寒雨  阅读(29)  评论(0)    收藏  举报