第十二天之STL算法设计理念_算法中的函数对象和谓词

函数对象和谓词定义

函数对象:
重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类
似函数的对象。一个类对象,表现出一个函数的特征,就是通过“对象名+(参数列表)”的方式
使用一个类对象,如果没有上下文,完全可以把它看作一个函数对待。
这是通过重载类的 operator()来实现的。
“在标准库中,函数对象被广泛地使用以获得弹性”,标准库中的很多算法都可以使用函数
对象或者函数来作为自定的回调行为;
谓词:
一元函数对象:函数参数 1 个;
二元函数对象:函数参数 2 个;
一元谓词 函数参数 1 个,函数返回值是 bool 类型,可以作为一个判断式
谓词可以使一个仿函数,也可以是一个回调函数。
二元谓词 函数参数 2 个,函数返回值是 bool 类型
一元谓词函数举例如下
1,判断给出的 string 对象的长度是否小于 6
bool GT6(const string &s)
{
return s.size() >= 6;
}
2,判断给出的 int 是否在 3 到 8 之间
bool Compare( int i )
{
return ( i >= 3 && i <= 8 );
}
二元谓词举例如下
1,比较两个 string 对象,返回一个 bool 值,指出第一个 string 是否比第二个短
bool isShorter(const string &s1, const string &s2)
{
return s1.size() < s2.size();
}

一元函数对象案例:

//1 普通类 重载 函数调用操作符
template <typename T>
void FuncShowElemt(T &t) //普通函数 不能像 仿函数那样记录状态
{
cout << t << " ";
};
void showChar(char &t)
{
cout << t << " ";
}
//函数模板 重载 函数调用操作符
template <typename T>
class ShowElemt
{
public:
ShowElemt()
{
n = 0;
}
void operator()(T &t)
{
n++;
cout << t << " ";
}
void printCount()
{
cout << n << endl;
}
public:
int n;
};
//1 函数对象 基本使用
void main11()
{
int a = 100;
FuncShowElemt<int>(a); //普通的函数调用
ShowElemt<int> showElemt; //函数对象
showElemt(a); //函数对象调用
}

一元谓词案例

//1 元谓词 例子
template <typename T>
class Isdiv
{
public:
Isdiv(const T &divisor) //
{
this->divisor = divisor;
}
bool operator()(T &t)
{
return (t%divisor == 0);
}
protected:
private:
T divisor;
};
void main13()
{
vector<int> v2;
for (int i=10; i<33; i++)
{
v2.push_back(i);
}
vector<int>::iterator it;
int a = 4;
Isdiv<int> mydiv(a);
// _InIt find_if(_InIt _First, _InIt _Last, _Pr _Pred) //返回的是迭代器
it = find_if(v2.begin(), v2.end(), Isdiv<int>(4));
if (it != v2.end())
{
cout << "第一个被 4 整除的数是:" << *it << endl;
} }

二元函数对象案例

template <typename T>
struct SumAdd
{
T operator()(T &t1, T &t2)
{
return t1 + t2;
}
};
template <typename T>
void printE(T &t)
{
for (vector<int>::iterator it = t.begin(); it!=t.end(); it++ )
{
cout << *it << " ";
} }
void printVector(vector<int> &v)
{
for (vector<int>::iterator it = v.begin(); it!=v.end(); it++ )
{
cout << *it << " ";
} }
void main14()
{
vector<int> v1, v2 ;
vector<int> v3;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v2.push_back(4);
v2.push_back(5);
v2.push_back(6);
v3.resize(10);
//transform(v1.begin(), v1.end(), v2.begin(),v3.begin(), SumAdd<int>());
/*
template<class _InIt1,
class _InIt2,
class _OutIt,
class _Fn2> inline
_OutIt transform(_InIt1 _First1, _InIt1 _Last1,
_InIt2 _First2, _OutIt _Dest, _Fn2 _Func)
*/
vector<int>::iterator it = transform(v1.begin(), v1.end(), v2.begin(),v3.begin(), 
SumAdd<int>());
cout << *it << endl;
printE(v3);
}

二元谓词案例

void current(int &v)
{
cout << v << " ";
}
bool MyCompare(const int &a, const int &b)
{
return a < b;
}
void main15()
{
vector<int> v(10);
for (int i=0; i<10; i++)
{
v[i] = rand() % 100;
}
for_each(v.begin(), v.end(), current);
printf("\n");
sort(v.begin(), v.end(), MyCompare );
printf("\n");
for (int i=0; i<10; i++)
{
printf("%d ", v[i]);
}
printf("\n");
}

综合案例:

#include<iostream>
using namespace std;
#include "list"
#include "vector"
#include "string"
#include "algorithm"
#include "set"
#include "functional"


//函数对象:类重载了()操作符 这种类的对象
template <typename T>
class ShowElem
{
public:
	ShowElem()
	{
		n = 0;
	}
	void operator()(T& t)
	{
		n++;
		//printN();
		cout << t << endl;
	}
	void printN()
	{
		cout << "n:" << n << endl;
	}
private:
	int n;
};
template <typename T>
void FuncShow(T &t)
{
	cout << t << endl;
}
//普通函数
void FuncShow2(int &t)
{
	cout << t << " ";
}
//函数对象和普通函数的区别
void main01()
{
	int a = 10;
	ShowElem<int> show;
	show(a);	//类对象的()调用很像函数的调用  又称为仿函数

	//普通函数与仿函数的区别
	FuncShow<int>(a);
	FuncShow2(a);
}
//函数对象的好处:函数对象是属于类对象的,能突破函数的概念,保持调用的状态
//函数对象的好处:
//for_each算法中,函数对象做函数参数
//for_each算法中,函数对象做返回值
void main02()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(3);
	v.push_back(5);

	for_each(v.begin(), v.end(),ShowElem<int>());	//匿名函数对象
	for_each(v.begin(), v.end(), FuncShow2);		//FuncShow2是回调函数的入口地址 谁使用for_each函数谁提供入口地址

	ShowElem<int> show;
	//函数对象做函数参数
	//for_each算法的 函数对象的传递 是值传递,不是引用传递 需要用show接返回值
	cout << "通过for_each函数的返回值查看调用的次数" << endl;
	show = for_each(v.begin(), v.end(), show);
	show.printN();

	//要点:分清楚STL返回值是迭代器还是谓词(函数对象)是STL算法入门的重点
	
}

template <typename T>
class ISDiv
{
public:
	ISDiv(const T &divs)
	{
		this->div = divs;
	}
	//一元谓词
	bool operator()(T &t)
	{
		return (t%div == 0);
	}
private:
	T div;
};
void main03()
{
	vector<int> v;
	for (int i = 10; i < 30;i++)
	{
		v.push_back(i);
	}
	int a = 4;
	ISDiv<int> MyDir(a);

	//find_if(v.begin(),v.end(),MyDir);

	vector<int>::iterator it;
	it = find_if(v.begin(), v.end(), ISDiv<int>(4));
	//find_if返回的是一个迭代器
	if (it==v.end())
	{
		cout << "容器中没有值是4的倍数" << endl;
	}
	else
	{
		cout << "第一个被4整除的数是:" << *it << endl;
	}
}

//二元函数对象
template <typename T>
class SumAdd
{
public:
	T operator()(T &t1, T &t2)
	{
		return t1 + t2;
	}
};
void main04()
{
	//v3=v1+v2
	vector<int> v1, v2, v3;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);

	v2.push_back(2);
	v2.push_back(4);
	v2.push_back(6);

	v3.resize(10);
	//v1.begin() + v2.begin() 赋值给v3.begin开始的容器,以SumAdd的方式
	transform(v1.begin(), v1.end() , v2.begin(), v3.begin() ,SumAdd<int>());
	//transform把运算结果的迭代器的地址返回出来
	for (vector<int>::iterator it = v3.begin();it != v3.end();it++)
	{
		cout << *it << " ";
	}
	cout << endl;

	for_each(v3.begin(), v3.end(), FuncShow2);	//FuncShow2回调函数
}

//二元谓词
bool MyCompare(const int &a, const int &b)
{
	return a < b;	//从小到大排序
}
void main05()
{
	vector<int> v(10);
	for (int i = 0; i < 10; i++)
	{
		int tmp = rand() % 100;
		v[i] = tmp;
	}
	for (vector<int>::iterator it = v.begin();it != v.end();it++)
	{
		cout << *it << " ";
	}
	cout << endl;

	//使用for_each函数遍历容器
	for_each(v.begin(), v.end(), FuncShow2);	//FuncShow2回调函数
	cout << endl;

	//排序算法
	sort(v.begin(), v.end(), MyCompare);   / /提供二元谓词
	for_each(v.begin(), v.end(), FuncShow2);	//FuncShow2回调函数
	cout << endl;



}
void main()
{
	//main01();
	//main02();
	//main03();//一元函数和一元谓词
	//main04();//二元函数和二元谓词
	main05();	
	system("pause");
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值