函数对象

1、什么是函数对象?

若一个类重载了()运算符,则该类的对象就称为函数对象。函数对象是个对象,但是用起来看上去象函数调用,实际上也执行了函数调用。

2、举栗子

class CMyAverage {
public:
	double operator()( int a1, int a2, int a3 ){//重载 () 运算符
		return (double)(a1 + a2+a3) / 3;
	}
};
void main(){
	CMyAverage average;		//函数对象
	cout << average(3,2,3); // average.operator()(3,2,3) 用起来看上去象函数调用 输出 2.66667
}

3、函数对象的应用

STL里有以下模板:

template<class InIt, class T, class Pred>
T accumulate(InIt first, InIt last, T val, Pred pr);
  • pr 就是个函数对象。对[first,last)中的每个迭代器 I,执行 val = pr(val,* I) ,返回最终的val。
  • Pr也可以是个函数。
//Dev C++ 中的 Accumulate 源代码1:
template<typename _InputIterator, typename _Tp>
_Tp accumulate(_InputIterator __first, _InputIterator__last,_Tp __init)
{
	for ( ; __first != __last; ++__first)
		__init = __init + *__first;
	return __init;
}

//Dev C++ 中的 Accumulate 源代码2:
template<typename _InputIterator, typename _Tp,
typename _BinaryOperation>
_Tp accumulate(_InputIterator __first, _InputIterator __last,_Tp __init,_BinaryOperation __binary_op)
{
	for ( ; __first != __last; ++__first)
		__init = __binary_op(__init, *__first);
	return __init;
}
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>
using namespace std;

int sumSquares( int total, int value)
{
	return total + value * value;
}
template <class T>
void PrintInterval(T first, T last)
{ //输出区间[first,last)中的元素
	for( ; first != last; ++ first)
		cout << * first << " ";
	cout << endl;
}

template<class T>
class SumPowers
{
private:
	int power;
public:
	SumPowers(int p):power(p) { }
	const T operator() ( const T & total,const T & value)
	{ //计算 value的power次方,加到total上
		T v = value;
		for( int i = 0;i < power - 1; ++ i)
			v = v * value;
		return total + v;
	}
};

int main()
{
	const int SIZE = 10;
	int a1[] = { 1,2,3,4,5,6,7,8,9,10 };
	vector<int> v(a1,a1+SIZE);
	cout << "1) "; PrintInterval(v.begin(),v.end());
	int result = accumulate(v.begin(),v.end(),0,SumSquares);
	cout << "2) 平方和:" << result << endl;
	result =accumulate(v.begin(),v.end(),0,SumPowers<int>(3));
	cout << "3) 立方和:" << result << endl;
	result =accumulate(v.begin(),v.end(),0,SumPowers<int>(4));
	cout << "4) 4次方和:" << result;
	return 0;
}
int result =accumulate(v.begin(),v.end(),0,SumSquares);
//实例化出:
int accumulate(vector<int>::iterator
first,vector<int>::iterator last,
int init,int ( * op)( int,int))
{
	for ( ; first != last; ++first)
		init = op(init, *first);
	return init;
}
accumulate(v.begin(),v.end(),0,SumPowers<int>(3));
//实例化出:
int accumulate(vector<int>::iterator first,
vector<int>::iterator last,
int init, SumPowers<int> op)
{
	for ( ; first != last; ++first)
		init = op(init, *first);
	return init;
}

4、STL 的< functional> 里还有以下函数对象类模板:

  • equal_to
  • greater
  • less

这些模板可以用来生成函数对象。

5、greater 函数对象类模板

template<class T>
struct greater : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const {
return x > y;
}
};
//binary_function定义:
template<class Arg1, class Arg2, class Result>
struct binary_function {
	typedef Arg1 first_argument_type;
	typedef Arg2 second_argument_type;
	typedef Result result_type;
};

6、greater 的应用

(1)list 有两个sort函数,前面例子中看到的是不带参数的sort函数,它将list中的元素按 < 规定的比较方法 升序排列。
(2)list还有另一个sort函数:可以用 op来比较大小,即 op(x,y) 为true则认为x应该排在前面.
template <class T2>
void sort(T2 op);
#include <list>
#include <iostream>
#include <iterator>
using namespace std;
class MyLess {
public:
	bool operator()( const int & c1, const int & c2 )
	{
		return (c1 % 10) < (c2 % 10);
	}
};

int main()
{
	const int SIZE = 5;
	int a[SIZE] = {5,21,14,2,3};
	list<int> lst(a,a+SIZE);
	lst.sort(MyLess());
	ostream_iterator<int> output(cout,",");
	copy( lst.begin(),lst.end(),output); 
	cout << endl;
	lst.sort(greater<int>()); //greater<int>()是个对象
	//本句进行降序排序
	copy( lst.begin(),lst.end(),output); 
	cout << endl;
	return 0;
} 输出:
21,2,3,14,5,
21,14,5,3,2,

7、ostream_iterator

copy类似于

template <class T1,class T2>
void Copy(T1 s,T1 e, T2 x)
{
	for(; s != e; ++s,++x)
	*x = *s;
}

ostream_iterator 如何编写?

#include <iostream>
#include <iterator>
using namespace std;
class MyLess
{
public:
	bool operator() (int a1,int a2)
	{
		if( ( a1 % 10 ) < (a2%10) )
			return true;
		else
			return false;
	}
};
bool MyCompare(int a1,int a2)
{
	if( ( a1 % 10 ) < (a2%10) )
		return false;
	else
		return true;
}

int main()
{
	int a[] = {35,7,13,19,12};
	cout << MyMax(a,5,MyLess()) << endl;
	cout << MyMax(a,5,MyCompare) << endl;
	return 0;
}
/*输出:
19
12
*/
要求写出MyMax


template <class T, class Pred>
T MyMax( T * p, int n, Pred myless)
{
	T tmpmax = p[0];
	for( int i = 1;i < n;i ++ )
		if( myless(tmpmax,p[i]))
			tmpmax = p[i];
	return tmpmax;
};

8、引入函数对象后,STL中的“大”,“小”关系

关联容器和STL中许多算法,都是可以自定义比较器的。在自定义了比较器op的情况下,以下三种说法是等价的:

  • x小于y
  • op(x,y)返回值为true
  • y大于x

9、比较规则的注意事项

struct 结构名
{
	bool operator()( const T & a1,const T & a2) {
		//若a1应该在a2前面,则返回true。
		//否则返回false。
	}
};
  • 排序规则返回 true,意味着 a1 必须在 a2 前面;返回 false,意味着 a1 并非必须在 a2 前面。
  • 排序规则的写法,不能造成比较 a1,a2 返回 true 比较 a2,a1 也返回 true,否则sort会 runtime error。
  • 比较 a1,a2 返回 false 比较 a2,a1 也返回 false,则没有问题。
posted @ 2019-12-16 20:09  江南又一春  阅读(158)  评论(0编辑  收藏  举报