函数只是表达一个运算过程,像沙漏,流过后不留下任何痕迹,如果遇到用一个函数统计容器所有Student对象的身高,就必须累加上次累加的结果。这时就必须用到函数对象。
函数对象:就是定义了函数调用操作符,即operator()的普通类的对象。
例如,可以定义一个函数对象类来实现比较两个数的大小
代码如下:
// 3.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
//模板函数对象的定义
template <typename T>
class mymax
{
public:
T operator ()( T a, T b)
{
return a > b ? a : b;
}
};
//利用函数对象定义函数模板
template <typename T>
T compare( T a, T b, mymax<T>& op)
{
return op(a, b);
}
int _tmain(int argc, _TCHAR* argv[])
{
//定义一个int类型的函数对象
mymax<int> intmax;
//直接对函数对象使用
int nMax1 = intmax(2, 3);
//作为参数传递给其他函数
int nMax2 = compare(1, 0, intmax);
return 0;
}
以下为解决上面提出的问题:
// 3.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//定义student类
class Student
{
public:
Student()
{
m_strName = "";
m_nHeight = 0;
}
public:
Student( string strName, int nHeight)
: m_strName(strName), m_nHeight(nHeight)
{
}
string GetName()
{
return m_strName;
}
int GetHeight()
{
return m_nHeight;
}
private:
string m_strName;
int m_nHeight;
};
//定义一个函数对象类
class AverageHeight
{
public:
//构造函数,对类的成员属性初始化
AverageHeight()
: m_nCount(0) , m_nTotalHeight(0)
{
};
//重载函数调用操作符“()”
//完成统计功能
void operator () ( Student st )
{
m_nTotalHeight += st.GetHeight();
++m_nCount;
}
//以下都是借口函数
float GetAverageHeight()
{
if ( 0 != m_nCount )
{
return (float)GetTotal()/GetCount();
}
}
int GetCount()
{
return m_nCount;
}
int GetTotal()
{
return m_nTotalHeight;
}
private:
int m_nCount;
int m_nTotalHeight;
};
int _tmain(int argc, _TCHAR* argv[])
{
vector<Student> vecStu;
Student st1( "zhouzhou", 180 );
Student st2( "xiaoxiao", 162 );
Student st3( "huhu", 176 );
vecStu.push_back(st1);
vecStu.push_back(st2);
vecStu.push_back(st3);
AverageHeight ah;
ah = for_each( vecStu.begin(), vecStu.end(), ah);
cout<<ah.GetCount()<<"个学生的平均身高是:"<<ah.GetAverageHeight()<<endl;
return 0;
}
为了减少定义函数对象类工作,STL预定义了许多常用的函数对象:
一、算术操作
这类对象可以用于常见的算术运算,例如,加(plus)、减(minus)、乘(multiplies)、除(divides)、取余(modules)和取负(negate)等
二、比较操作
这类对象可以用于进行数据的比较,例如,等于(equal_to)、不等于(not_equal_to)、大于(greater)、小于(less)、大于等于(greater_equal)、小于等于(less_equal)
三、逻辑操作
这类对象可以用来逻辑运算,例如,逻辑与(logical_and)、逻辑或(logical_or)、逻辑非(logical_not)
例如:
统计容器中大于60的数据个数
int nCount = count_if( vecScore.begin(), vecScore.end(), bind2nd( greater<int>(), 60) );