STL学习(12):函数对象

本文详细介绍了STL中的函数对象,包括一元函数、二元函数、系统函数对象、函数适配器及其应用。函数对象是重载了operator()的类,用于简化程序结构。讲解了如何使用函数对象进行操作,如一元函数和二元函数的模板类,以及算术、关系和逻辑运算类的系统函数对象。函数适配器如bind1st、bind2nd和not1、not2等的使用,增强了函数对象的功能和灵活性。
摘要由CSDN通过智能技术生成

为何引入函数对象

即在函数中调用所需类对象的函数,使程序结构同时显得非常简洁 。

 

函数对象是重载了operator()的类的一个实例,operator()是函数调用运算符。标准C++库根据operator()参数个数为0个,1个,2个加以划分的。

主要有以下3种类型:

  • 发生器:一种没有参数且返回一个任意类型值的函数对象,例如随机数发生器。
  • 一元函数:一种只有一个任意类型的参数,且返回一个可能不同类型值的函数对象。
  • 二元函数:一种有两个任意类型的参数,且返回一个任意类型值的函数对象。
  • 一元判定函数:返回bool型值的一元函数
  • 二元判定函数: 返回bool型值的二元函数
class CSum
{
private:
	int sum;
public:
	CSum(){sum = 0;}
	void operator()(int n)
    {
        sum += n;
    }
    int GetSum(){return sum;}
};

int main()
{
    vector<int> v ;
    for(int i=1; i<=100; i++)
    {
        v.push_back(i);
    }
    CSum sObj = for_each(v.begin(), v.end(), CSum());
    printf("sum=%d\n", sObj.GetSum());
}

必须重载operator()函数:这是实现函数对象功能最重要的环节,不能随便写,因此6.1.1节中CSum类中的f(int)函数修改为operator()(int), 而函数体的内容不变。

函数对象调用方式:直接采用构造函数调用,如本例中for_each(v.begin(), v.end(), CSum())中的第3个参数CSum(), 也就是说:对本例而言,STL知道CSum()对应着CSum类中重载的operator()函数,具体有几个参数呢,由于for_each函数一次只能迭代出一个整形数,所以STL知道每迭代一次整形数,都要执行一次CSum中的operator()(int)函数。

CSum sObj是用来接收for_each迭代函数对象的最终结果值的。

一元函数

STL中一元函数基类是一个模板类,原形如下:

template<class _A, class _R>
struct unary_function {
    typedef _A argument_type;     
    typedef _R result_type;
};

它有两个模板参数,_A是输入参数,_R是返回类型,且此两个参数的类型是任意的,因此,它的动态特性非常强。

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;

template<typename _inPara, typename _outPara>
class CSum : public unary_function<_inPara, _outPara>
{
public:
	_outPara sum;
     CSum(){sum = 0;}
     void operator()(_inPara n)
	{
	    sum += n;
     }
     _outPara GetSum(){return sum;}
};

int main()
{
	vector<int> v ;
	for(int i=1; i<=100; i++)
	{
	v.push_back(i);
	}
	CSum<int,int> sObj=for_each(v.begin(), v.end(), CSum<int, int>());
	cout << "sum(int)=" << sObj.GetSum() << endl;

	vector<float> v2 ;
	float f = 1.3f;
	for(int i=1; i<=99; i++)
	{
        v2.push_back(f);
	   f += 1.0f;
	}
	CSum<float,float> sObj2=for_each(v2.begin(), v2.end(), CSum<float, float>());
	cout << "sum(float)=" << sObj2.GetSum() << endl;
}

主要理解以下几点。

(1)应用STL模板一元函数必须从unary_function基类派生。例如本例中的CSum类。

(2)加深对一元函数模板类模板参数的理解。例如本例中的_inPara表示的是operator()函数的参数类型,所以写作void operator()(_inPara n),_outPara表示的是返回值的类型,因此返回值变量sum应定义成_outPara类型。由于此两个参数在本例中都是动态传进去的,因此在类定义的前面要加上template<class _inPara, class _outPara>。

(3)对调用模板函数对象方式的理解。例如本例中    CSum<int,int> sObj=for_each(v.begin(), v.end(), CSum<int, int>())表明是对整形向量元素求和,CSum<int,int>表明CSum是一个模板类,两个动态参数都是整形数;CSum<float,float> sObj2=for_each(v2.begin(), v2.end(), CSum<float, float>())表明是对浮点向量元素求和,两个动态参数都是浮点型。可以看出对整形向量求和、浮点向量求和都是由CSum函数对象类完成的,当然也可用CSum求其它数据类型的和,从中可以体会出STL中一元函数模板类功能的强大。 

二元函数

STL中二元函数基类是一个模板类,原形如下所示。

template<class Arg1, class Arg2, class Result>
struct binary_function {
    typedef Arg1 first_argument_type;
    typedef Arg2 second_argument_type;
    typedef Result result_type;
};	

它有三个模板参数,Arg1、Arg2是输入参数,Result是返回类型,且此三个参数的类型是任意的,因此,它的动态特性非常强。

利用二元函数使学生成绩升序排列。

class Student
{
public:
	string name;
	int grade;
public:
	Student(string name, int grade)
	{
		this->name = name;
		this->grade
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值