仿函数即定义了operator()的对象。
如:FuncitonObjectTypeClass fo;
fo(...);
其中fo()是调用fo的operator(),而非调用fo().这一点很重要是核心。
也就是说并不是将所有语句放在一般的函数中。
void fo(){ statements}
而是放在operator()中如下:
class FuncitonObjectTypeClass
{
public:
void operator()()
{
statements;
}
}
这个特性常用在有序的容器中。如以下。
对一个拥有Person对象的容器,按照Person的名称进行排序,要是名称相同按照年龄排序。
则可以这样使用。
//二段判式
class Person
{
public:
string name;
int age;
};
class PersonSortCriterion
{
public :
bool operator() (const Person& p1,const Person& p2) const
{
return p1.name < p2.name ||
((p1.name == p2.name) && p1.age < p2.age);
}
};
测试代码如下:
Person per1;
per1.name = "aaaa";
per1.age = 23;
Person per2;
per2.name = "aaab";
per2.age = 24;
Person per3;
per3.name = "aaaa";
per3.age = 21;
Person per4;
per4.name = "bbbb";
per4.age = 21;
cout<<"----Person仿函数排序----start--"<<endl;
typedef set<Person,PersonSortCriterion> PersonSet;
PersonSet personSotFunction;
personSotFunction.insert(per1);
personSotFunction.insert(per2);
personSotFunction.insert(per3);
personSotFunction.insert(per4);
PersonSet::iterator posPersonSet;
for (posPersonSet = personSotFunction.begin();posPersonSet != personSotFunction.end();++posPersonSet)
{
cout<<"personName: "<<(*posPersonSet).name<<" personAge: "<<(*posPersonSet).age<<endl;
}
cout<<"----Person仿函数排序----end--"<<endl;
第二:拥有内部状态的仿函数。注意仿函数都是按值传递,并不是按址传递。所以调用后并不会改变仿函数的内部状态。示例代码如下。
实例1:产生一个初始值的序列。每次调用都为序列加1
//仿函数如下:
//以初始化数累加的序列
class IntSequence
{
private:
int value;
public:
IntSequence(int initialValue):value(initialValue)
{
}
int operator()()
{
return value++;
}
};
//测试代码如下,其中PRINT_ELEMENTS是用于打印容器元素的。
cout<<"-------functors------------"<<endl;
list<int> listFuctor;
IntSequence seq(1);
generate_n(back_inserter(listFuctor),4,seq);
PRINT_ELEMENTS(listFuctor,"Value: ");
generate_n(back_inserter(listFuctor),4,IntSequence(42));
PRINT_ELEMENTS(listFuctor,"insertValue: ");
generate_n(back_inserter(listFuctor),4,seq);
PRINT_ELEMENTS(listFuctor,"RepeatSeq: ");
//PRINT_ELEMENTS,是个模板方法,方法如下
template<class T>
inline void PRINT_ELEMENTS(const T& coll, const char* optcstr)
{
typename T::const_iterator pos;
std::cout << optcstr;
for(pos = coll.begin();pos != coll.end();++pos)
{
std::cout<< *pos << ' ';
}
std::cout<<std::endl;
}
![](https://img-my.csdn.net/uploads/201208/22/1345630350_1331.png)
cout<<"-------functors------------"<<endl;
list<int> listFuctor;
IntSequence seq(1);
generate_n<back_insert_iterator<list<int> >,int,IntSequence& >(back_inserter(listFuctor),4,seq);
PRINT_ELEMENTS(listFuctor,"ByReference: ");
generate_n(back_inserter(listFuctor),4,IntSequence(42));
PRINT_ELEMENTS(listFuctor,"insertValue: ");
generate_n(back_inserter(listFuctor),4,seq);
PRINT_ELEMENTS(listFuctor,"RepeatSeq: ");
由结果可以看出,IntSeque仿函数的内部状态并没有因为第一次的调用而被改变。所以要注意仿函数是按值来传递参数的。
实例二:for_each()的返回值。for_each的独特之处在于可以返回仿函数,这样就额可以通过for_each()的返回值来获取仿函数的状态。这里的状态其实也可以理仿函数中的某一个成员变量的返回值,或者某一个成员变量的值。
//定义仿函数
//求平均数的仿函数
class MeanValue
{
private:
long num;
long sum;
public:
MeanValue():num(0),sum(0)
{
}
void operator()(int elem)
{
num++;
sum += elem;
}
double value()
{
return static_cast<double>(sum) / static_cast<double>(num);
}
};
//调用的地方:
cout<<"==========for_each返回值============"<<endl;
list<int> collRepeatList;
for (index = 1;index < 9;++index)
{
collRepeatList.push_back(index);
}
PRINT_ELEMENTS(collRepeatList,"collRepeat: ");
MeanValue mv = for_each(collRepeatList.begin(),collRepeatList.end(),MeanValue());
cout<<"MeanValue: "<<mv.value()<<endl;
注意其中的for_each的值。它返回仿函数后,就可以调用仿函数的value方法。这个用法相当的灵活。for_each的独门绝技啊。O(∩_∩)O~
结果如下:
仿函数就介绍这些基本的应用。下面介绍适配器的一些实用。由于篇幅太长。改在下一篇中介绍吧。