函数对象的理解

一、函数对象的定义

首先有这么一个类,它重载了函数调用操作符[operator()],那么这个类定义的对象就叫做函数对象。关键的一点是:这个类重载了函数调用操作符“()”。那么为什么称为函数对象呢?针对与这一点的理解,下面会讲到。

二、先看一个函数对象的实例

//定义一个类LessThan,重载了函数调用操作符"()"
class LessThan
{
public:
	bool operator() (int val)//重载函数调用操作符"()"
	{
		return val <= 10 ; //判断一个值是否小于等于10
	}
};

//泛型算法使用函数对象作为实参
count_if(vec.begin(),vec.end(),LessThan()) ;

       我们可以看到定义了一个类LessThan,该类重载了函数调用操作符“()”,上面的count_if是一个泛型算法,那么我们是如何在这个泛型算法中使用函数对象呢?一般而言,我们要使用函数对象,向泛型算法中传递一个类对象即可,该算法会自动调用该对象重载的operator()操作符。针对于上面count_if函数的第三个参数为LessThan(),这个是显示调用构造函数创建了一个对象,所以,我们想泛型函数传递了一个类对象,这样就可以保证该算法会调用该对象的重载的operator()操作符。那么为什么称为函数对象呢?那是因为通过类创建一个对象实例时(LessThan()),像是是函数调用,所以将其称为函数对象。

三、函数对象的注意点

1、函数调用操作符必须声明为成员函数,一个类可以定义函数调用操作符的多个版本,由形参的数目和类型加以区分。

2、定义了函数调用操作符的类,它的对象称为函数对象,即也就是说它们是行为类似函数的对象。

3、函数对象通常是用作同样算法的实参。例如上面的count_if中的第三个实参。

四、函数对象的具体实例解释

//定义absInt类,该类重载了函数调用操作符"()"
class absInt
{
public:
	int operator()(int val) //重载函数调用操作符"()"
	{
		int result = val < 0 ? -val : val ;
		return result ;
	}
};

#include <vector>
#include <algorithm>

int main()
{
	int ia[] = {-0,1,-1,-2,3,5,-5,8} ;
	vector<int> ivec(ia,ia+8) ;

	//把ivec的每个元素设置为其绝对值
	transform(ivec.begin(),ivec.end(),ivec.begin(),absInt()) ;
	// ... 
}
/*
1、transform是一个泛型函数。transform的第一个和第二个实参指示absInt操作被应用的元素范围。第二个实参
指向"被用来存储absInt操作结果的向量"的开始

2、transform的第四个参数是一个absInt类的临时对象,它通过显示调用absInt的缺省构造函数来创建。
*/

//main调用的泛型算法transform的实例看起来像这样:
typedef vector<int>::iterator iter_type ;
//transform()的实例把操作ansInt应用到int型vector的所有元素上
iter_type transform(iter_type iter,iter_type last, iter_type result,absInt func) //定义了func对象。func是函数对象
{
	while(iter != last)
		*result++ = func(*iter++) ; //调用absInt::operate()
	return iter ;
}
/*
func是一个类类型的对象,它的类型代表ansInt操作,该操作把int型的值设置为其绝对值。对象func被用来调用
ansIntabsInt类的重载的operator()。传递给这个重载操作符的实参是*iter,它指向我们想获取其绝对值的那个
向量元素。
*/


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值