栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

STL函数对象、谓词、内建函数、适配器

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

STL函数对象、谓词、内建函数、适配器

函数对象(仿函数)

重载函数调用操作符()的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象,也叫仿函数(functor),其实就是重载“()”操作符,使得类对象可以像函数那样调用。
注意:
1.函数对象(仿函数)是一个类,不是一个函数。
2.函数对象(仿函数)重载了”() ”操作符使得它可以像函数一样调用。

函数对象特点
//函数对象是重载了函数调用符号的类
class MyPrint
{
public:
	MyPrint()
	{
		m_Num = 0;
	}
	int m_Num;

public:
	void operator() (int num)
	{
		cout << num << endl;
		m_Num++;
	}
};

//函数对象
//重载了()操作符的类实例化的对象,可以像普通函数那样调用,可以有参数 ,可以有返回值
void test01()
{
	MyPrint myPrint;
	myPrint(20);

}
// 函数对象超出了普通函数的概念,可以保存函数的调用状态
void test02()
{
	MyPrint myPrint;
	myPrint(20);
	myPrint(20);
	myPrint(20);
	cout << myPrint.m_Num << endl;
}

void doBusiness(MyPrint print,int num)
{
	print(num);
}

//函数对象作为参数
void test03()
{
	//参数1:匿名函数对象
	doBusiness(MyPrint(),30);//Myprint()匿名对象
}

1、函数对象通常不定义构造函数和析构函数,所以在构造和析构时不会发生任何问题,避免了函数调用的运行时问题。
2、函数对象超出普通函数的概念,函数对象可以有自己的状态
3、函数对象可内联编译,性能好。用函数指针几乎不可能
4、模版函数对象使函数对象具有通用性,这也是它的优势之一

谓词

谓词是指普通函数或重载的operator()返回值是bool类型的函数对象(仿函数)。如果operator接受一个参数,那么叫做一元谓词,如果接受两个参数,那么叫做二元谓词,谓词可作为一个判断式。

class GreaterThenFive
{
public:
	bool operator()(int num)//一元谓词
	{
		return num > 5;
	}

};
//一元谓词
void test01()
{
	vector v;
	for (int i = 0; i < 10;i ++)
	{
		v.push_back(i);
	}
	
	 vector::iterator it =  find_if(v.begin(), v.end(), GreaterThenFive());//第三个参数是函数对象
	 if (it == v.end())
	 {
		 cout << "没有找到" << endl;
	 }
	 else
	 {
		 cout << "找到了: " << *it << endl;
	 }
}

//二元谓词
class MyCompare
{
public:
	bool operator()(int num1, int num2)//二元谓词
	{
		return num1 > num2;
	}
};

void test02()
{
	vector v;
	v.push_back(10);
	v.push_back(40);
	v.push_back(20);
	v.push_back(90);
	v.push_back(60);

	//默认从小到大
	sort(v.begin(), v.end());
	for (vector::iterator it = v.begin(); it != v.end();it++)
	{
		cout << *it << " ";
	}
	cout << endl;
	cout << "----------------------------" << endl;
	//使用函数对象改变算法策略,排序从大到小
	sort(v.begin(), v.end(),MyCompare());
	for (vector::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}
  //匿名函数  lambdab表达式写法[](参数){函数体}
  for_each(v.begin(),v.end(),[](int val){cout< 
内建函数 

STL内建了一些函数对象。分为:算数类函数对象,关系运算类函数对象,逻辑运算类仿函数。这些仿函数所产生的对象,用法和一般函数完全相同,当然我们还可以产生无名的临时对象来履行函数功能。使用内建函数对象,需要引入头文件 #include

  • 6个算数类函数对象,除了negate是一元运算,其他都是二元运算。
template T plus//加法仿函数
template T minus//减法仿函数
template T multiplies//乘法仿函数
template T divides//除法仿函数
template T modulus//取模仿函数
template T negate//取反仿函数
  • 6个关系运算类函数对象,每一种都是二元运算。
template bool equal_to//等于
template bool not_equal_to//不等于
template bool greater//大于
template bool greater_equal//大于等于
template bool less//小于
template bool less_equal//小于等于
  • 逻辑运算类运算函数,not为一元运算,其余为二元运算。
template bool logical_and//逻辑与
template bool logical_or//逻辑或
template bool logical_not//逻辑非

内建函数对象举例:

//取反仿函数
void test01()
{
	negate n;
	cout << n(50) << endl;
}

//加法仿函数
void test02()
{
	plus p;
	cout << p(10, 20) << endl;
}

//大于仿函数
void test03()
{
	vector v;
	srand((unsigned int)time(NULL));
	for (int i = 0; i < 10; i++){
		v.push_back(rand() % 100);
	}

	for (vector::iterator it = v.begin(); it != v.end(); it++){
		cout << *it << " ";
	}
	cout << endl;
	sort(v.begin(), v.end(), greater());//使用greater内建函数

	for (vector::iterator it = v.begin(); it != v.end(); it++){
		cout << *it << " ";
	}
	cout << endl;

}
适配器 函数适配器

1.给函数对象绑定参数
2.根据我们函数对象是一元函数对象 还是二元函数对象,使自己的函数对象继承于binary_function(二元) 或者 unary_function(一元)
3.加const修饰operator()函数

总结: bind1st和bind2nd区别?

  • bind1st : 将参数绑定为函数对象的第一个参数
  • bind2nd : 将参数绑定为函数对象的第二个参数
  • bind1st bind2nd将二元函数对象转为一元函数对象
//函数适配器bind1st bind2nd
//现在我有这个需求 在遍历容器的时候,我希望将容器中的值全部加上100之后显示出来,怎么做?
//我们直接给函数对象绑定参数 编译阶段就会报错
//for_each(v.begin(), v.end(), bind2nd(myprint(),100));
//如果我们想使用绑定适配器,需要我们自己的函数对象继承binary_function 或者 unary_function
//根据我们函数对象是一元函数对象 还是二元函数对象
class MyPrint :public binary_function//<参数类型,参数类型,返回值类型>
{
public:
	void operator()(int v1,int v2) const//指定为常函数,不允许修改值
	{
		cout << "v1 = : " << v1 << " v2 = :" <v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	cout << "请输入起始值:" << endl;
	int x;
	cin >> x;

	for_each(v.begin(), v.end(), bind1st(MyPrint(), x));
	//for_each(v.begin(), v.end(), bind2nd( MyPrint(),x ));
}
//总结:  bind1st和bind2nd区别?
//bind1st : 将参数绑定为函数对象的第一个参数
//bind2nd : 将参数绑定为函数对象的第二个参数
//bind1st bind2nd将二元函数对象转为一元函数对象

取反适配器

not1 对一元函数对象取反
not2 对二元函数对象取反

class GreaterThenFive:public unary_function
{
public:
	bool operator ()(int v) const
	{
		return v > 5;
	}
};

//2、取反适配器
void test02()
{
    //一元取反
	vector  v;
	for (int i = 0; i < 10;i++)
	{
		v.push_back(i);
	}
	
// 	vector::iterator it =  find_if(v.begin(), v.end(), GreaterThenFive()); //返回第一个大于5的迭代器
//	vector::iterator it = find_if(v.begin(), v.end(),  not1(GreaterThenFive())); //返回第一个小于5迭代器,not1的1代表一元取反
	//自定义输入
	vector::iterator it = find_if(v.begin(), v.end(), not1 ( bind2nd(greater(),5)));//greater为内建函数
	if (it == v.end())
	{
		cout << "没找到" << endl;
	}
	else
	{
		cout << "找到" << *it << endl;
	}

	//排序  二元函数对象
	sort(v.begin(), v.end(), not2(less()));
	for_each(v.begin(), v.end(), [](int val){cout << val << " "; });

}
//not1 对一元函数对象取反
//not2 对二元函数对象取反
函数指针适配器

ptr_fun( )把一个普通的函数指针适配成函数对象(仿函数)

void MyPrint03(int v,int v2)
{
	cout << v + v2<< " ";
}

//3、函数指针适配器   ptr_fun
void test03()
{
	vector  v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	// ptr_fun( )把一个普通的函数指针适配成函数对象
	for_each(v.begin(), v.end(), bind2nd( ptr_fun( MyPrint03 ), 100));
}
成员函数适配器

mem_fun_ref 将Person内部成员函数适配为函数对象(仿函数)

  • 如果容器存放的是对象指针, 那么用mem_fun
  • 如果容器中存放的是对象实体,那么用mem_fun_ref
class Person
{
public:
	Person(string name, int age)//有参构造
	{
		m_Name = name;
		m_Age = age;
	}

	//打印函数
	void ShowPerson(){
		cout << "成员函数:" << "Name:" << m_Name << " Age:" << m_Age << endl;
	}
	void Plus100()
	{
		m_Age += 100;
	}
public:
	string m_Name;
	int m_Age;
};

void MyPrint04(Person &p)///回调函数
{
	cout << "姓名:" <<  p.m_Name << " 年龄:" << p.m_Age << endl;

};

void test04()
{
    //容器中存放对象实体
	vector v;
	Person p1("aaa", 10);
	Person p2("bbb", 20);
	Person p3("ccc", 30);
	Person p4("ddd", 40);
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);

	//for_each(v.begin(), v.end(), MyPrint04);//myprint04回调函数
	//利用 mem_fun_ref 将Person内部成员函数适配
	for_each(v.begin(), v.end(), mem_fun_ref(&Person::ShowPerson));
 	for_each(v.begin(), v.end(), mem_fun_ref(&Person::Plus100));
   //容器中存放的对象实体使用em_fun_ref 
}

void test05(){
    //容器中存放对象指针
	vector v1;
	//创建数据
	Person p1("aaa", 10);
	Person p2("bbb", 20);
	Person p3("ccc", 30);
	Person p4("ddd", 40);

	v1.push_back(&p1);
	v1.push_back(&p2);
	v1.push_back(&p3);
	v1.push_back(&p4);
    //容器中存放的函数指针,使用em_fun
	for_each(v1.begin(), v1.end(), mem_fun(&Person::ShowPerson));
}

//如果容器存放的是对象指针,  那么用mem_fun
//如果容器中存放的是对象实体,那么用mem_fun_ref
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/317723.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号