1 仿函数也称为函数对象,是一种具有函数特质的对象。调用者可以像函数一样的使用这些对象,例如在很多STL算法中,都可以看到,我们可以将一个方法作为模板内的参数传入到算法实现中,例如sort的时候我们可以根据我们传入的自定义的compare函数来进行比较排序。解决办法是使用函数指针,或者是将这个“操作”设计为一个所谓的仿函数,再用这个仿函数生成一个对象,并用这个对象作为算法的一个参数。
2 那为什么STL不使用函数指针而使用仿函数呢,因为函数指针不能满足STL对抽象性的要求,无法和STL的其他组件搭配以产生更加灵活的效果。
3 怎样实现这样一个仿函数呢?(可以直接使用对象名来使用函数)?答:我们必须自定义或者重载函数调用的运算符operator (),先产生类对象的一个匿名对象,再调用相应的函数。
4 STL仿函数应该有能力被函数适配器修饰,就像积木一样串接,然而,为了拥有配接能力,每个仿函数都必须定义自己的associative types(主要用来表示函数参数类型和返回值类型),就想迭代器如果要融入整个STL大家庭,也必须按照规定定义自己的5个相应的类型一样,这些assocaiative type是为了让配接器可以取得仿函数的某些信息,当然,这些associative type都只是一些typedef,所有必要操作在编译器就全部完成了,对程序的执行效率没有任何影响,不会带来额外的负担。
5 unary_function
用来呈现一元函数的参数类型和返回值类型
<span style="font-family:Microsoft YaHei;font-size:18px;">Template<class Arg, class Result>
Struct unary_function
{
Typedef Arg argument_type;
Typedef Result result_type;
}
//自定义的一元仿函数可以继承上类来获得类型定义
Template<class T>
Struct negate:public unary_function<T,T>
{
T operator()(const T& x)const {return –x;}
};</span>
6 binary_function
用来呈现二元函数的第一个参数类型,第二个参数类型,和返回值类型
<span style="font-family:Microsoft YaHei;font-size:18px;">Template<class Arg1, class Arg2, class Result>
Struct binary_function
{
Typedef Arg1 first_argument_type;
Typedef Arg2 second_argument_type;
Typedef Result result_type;
};
//use
Template<class T>
Struct plus: public binary_function<T,T,T>
{
T operator()(const T& x, const T& y)const {return x+y ;}
};</span>
<span style="font-family:Microsoft YaHei;font-size:18px;">//适配器 前瞻(后文会介绍),使用组合而不是继承
Template<class Operation>
Class binder1st
{
Protected:
Operation op;
Typename Operation:first_argument_type value;
Public:
Typename Operation::result type operation() ( const typename Operation::second_argument_type& x)const;
} ;</span>
7 STL内建的“算术类仿函数”,支持 加法,减法,乘法,除法,模数,否定
<span style="font-family:Microsoft YaHei;font-size:18px;">#include<iostream>
#include<functional>
Using namespace std ;
Int main()
{
Plus<int> plusobj;
Cout<<plusobj(3,5)<<endl;
Cout<<plus<int>(3,5)<<endl;
// accumulate( iv.begin(), iv.begin(),1 , multiplies<int>());
}</span>
8 STL内建的关系运算仿函数支持 等于,不等于,大于,大于等于,小于,小于等于
<span style="font-family:Microsoft YaHei;font-size:18px;">#include<iostream>
#include<functional>
Using namespace std;
Int main()
{
Equal_to<int> qual_to_obj;
Cout<equal_to_obj(3,5)<<endl;
Cout<<equal_to<int>(3,5)<<endl;
// sort ( iv.begin(), iv.end(), greater<int>());
}</span>
9 STL内建支持 逻辑运算仿函数, and or not
<span style="font-family:Microsoft YaHei;font-size:18px;">#include<iostream>
#include<functional>
Using namespace std;
Int main()
{
Logical_and<int> and_obj; //注意这里的参数类是int
Cout<<and_obj(true, true)<<endl;
Cout<<logical_and<int>(true,true)<<endl;
}</span>
10 证同(identity)、选择(select)、投射(project)
template <class T> //返回本身
struct identity : public unary_function<T, T> {
const T& operator()(const T& x) const { return x; }
};
template <class Pair> //接受一个pair,返回第一个元素
struct select1st : public unary_function<Pair, typename Pair::first_type> {
const typename Pair::first_type& operator()(const Pair& x) const
{
return x.first;
}
};
template <class Pair> //接受一个pair,返回第二个元素
struct select2nd : public unary_function<Pair, typename Pair::second_type> {
const typename Pair::second_type& operator()(const Pair& x) const
{
return x.second;
}
};
投射函数
template <class Arg1, class Arg2> //传回第一参数,忽略第二参数
struct project1st : public binary_function<Arg1, Arg2, Arg1> {
Arg1 operator()(const Arg1& x, const Arg2&) const { return x; }
};
template <class Arg1, class Arg2> //传回第二参数,忽略第一参数
struct project2nd : public binary_function<Arg1, Arg2, Arg2> {
Arg2 operator()(const Arg1&, const Arg2& y) const { return y; }
};