Functor 仿函数

5 篇文章 0 订阅
2 篇文章 0 订阅
  仿函数,就是使一个类的使用看上去象一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了。   在我们写代码时有时会发现有些功能的实现的代码,会不断的在不同的成员函数中用到,但是又不好将这些代码独立出来成为一个类的一个成员函数。但是又很想复用这些代码。写一个公共的函数,可以,这是一个解决方法,不过函数用到的一些变量,就可能成为公共的全局变量,再说为了复用这么一片代码,就要单立出一个函数,也不是很好维护。这时就可以用仿函数了,写一个简单类,除了那些维护一个类的成员函数外,就只是实现一个operator(),在类实例化时,就将要用的,非参数的元素传入类中。这样就免去了对一些公共变量的全局化的维护了。又可以使那些代码独立出来,以便下次复用。而且这些仿函数,还可以用关联,聚合,依赖的类之间的关系,与用到他们的类组合在一起,这样有利于资源的管理(这点可能是它相对与函数最显著的有点了)。如果在配合上模板技术和policy编程思想,那就更是威力无穷了,大家可以慢慢的体会。
例如:
using namespace std;
//create a vector
vector<int> v;
//populate the vector
v.push_back(2);
v.push_back(3);
v.push_back(1);
v.push_back(5);
v.push_back(4);
struct reverseSort
{
   bool operator()(int a, int b) { return b < a; }
};
//sort the elements using custom functor
sort(v.begin(), v.end(), reverseSort());
//v = {5, 4, 3, 2, 1}
1.仿函数
1.1 定义:
      本质是一个类,是一个像使用函数一样直接名称+括号就可以调用的类,事实上就是一个重载了operator()函数的类。
1.2 目的:
      具有内部状态的功能,这是函数所不能比拟的。
1.3 例子:
view plaincopy to clipboardprint?
#include "stdafx.h"  
#include <vector>  
#include <string>  
#include <algorithm>  
#include <iostream>  
 
using std::string;  
 
class Person  
{  
public:  
    Person(string init): name(init)  
    {  
    }  
    string name;  
};  
 
class PersonCriterion   //这个就是仿函数,用于比较两个名字的长短  
{  
public:  
    bool operator() (const Person& t1, const Person& t2)  
    {  
        std::cout << "第" << ++count << "次调用" << std::endl;  //通过他可以很清晰地知道函数调用多少次  
        return t1.name.length() < t2.name.length();  
    }  
private:  
    static int count;  
};  
int PersonCriterion::count = 0;  
 
int _tmain(int argc, _TCHAR* argv[])  
{  
    std::vector<Person> iv;  
    iv.push_back(Person("one"));  
    iv.push_back(Person("two"));  
    iv.push_back(Person("three"));  
    iv.push_back(Person("four"));  
 
    //将类像函数一样将指针传递进去,sort将调用 PersonCriterion::operator() 对vector进行排序。  
    std::sort(iv.begin(), iv.end(), PersonCriterion() );  
 
    for (std::vector<Person>::iterator it = iv.begin();  
        it != iv.end();  
        ++it)  
    {  
        std::cout << (*it).name << " ";  
    }  
    return 0;  

最后的结果可能根据STL的实作可能会有所区别。
2 函数配接器:
2.1 定义:
      函数配接器是一种特殊的仿函数。能够将仿函数和另外一个仿函数结合起来的函数或者说是一个将仿函数作为参数的仿函数。预先定义好的函数配接器有
            bind1st(op, value),
            bind2nd(op, value),
            not1(op),
            not2(op)
2.2 分类:
      函数适配器有两种:
            针对一般函数(非成员函数)而设计的函数适配器
            针对成员函数而设计的函数适配器
2.3 针对一般函数(非成员函数)而设计的函数适配器:
      这种是我们最经常使用的用法。通过函数适配器对一个参数进行绑定。
view plaincopy to clipboardprint?
#include "stdafx.h"  
#include <vector>  
#include <string>  
#include <algorithm>  
#include <iostream>  
 
using std::string;  
 
class Person  
{  
public:  
    Person(string init): name(init)  
    {  
    }  
    string name;  
};  
 
bool  shorter (const Person& t1, const Person& t2)  
{  
    return t1.name.length() < t2.name.length();  
}  
 
 
int _tmain(int argc, _TCHAR* argv[])  
{  
    std::vector<Person> iv;  
    iv.push_back(Person("one"));  
    iv.push_back(Person("two"));  
    iv.push_back(Person("three"));  
    iv.push_back(Person("four"));  
 
    //将函数指针传递进去  
    std::sort(iv.begin(), iv.end(), shorter);  
 
    for (std::vector<Person>::iterator it = iv.begin();  
        it != iv.end();  
        ++it)  
    {  
        std::cout << (*it).name << " ";  
    }  
    return 0;  

2.4 针对成员函数而设计的函数配接器
      这里所说的成员函数不包括operator(). 这种用法不多见。是通过mem_fun_ref进行转换,将原本针对某个元素的函数调用转为调用被传递变量(*itr  itr为iv的迭代器)的成员函数。
view plaincopy to clipboardprint?
#include "stdafx.h"  
#include <vector>  
#include <string>  
#include <functional>  
#include <algorithm>  
#include <iostream>  
 
using std::string;  
 
class Person  
{  
public:  
    Person(string init): name(init)  
    {  
    }  
 
    //以成员函数调用,故可忽略const Person& t1  
    bool shorter(const Person& t2) const 
    {  
        std::cout << "第" << ++count << "次调用" << std::endl;  
        return name.length() < t2.name.length();  
    }  
    string name;  
    static int count;  
};  
int Person::count = 0;  
 
 
int _tmain(int argc, _TCHAR* argv[])  
{  
    std::vector<Person> iv;  
    iv.push_back(Person("one"));  
    iv.push_back(Person("two"));  
    iv.push_back(Person("three"));  
    iv.push_back(Person("four"));  
 
    std::sort(iv.begin(), iv.end(), std::mem_fun_ref(&Person::shorter) );  
 
    for (std::vector<Person>::iterator it = iv.begin();  
        it != iv.end();  
        ++it)  
    {  
        std::cout << (*it).name << " ";  
    }  
    return 0;  

2.5 可以使用函数配接器的自定义仿函数
      函数配接器只能用在系统仿函数(例如less)中,如果我们想要我们的仿函数能够使用函数配接器,必须然类从unary_function或binary_function派生而来。因为函数适配器里面用到了参数的特定成员(例如T1::argument_type, T1::result_type),所以我们只要在类继承列表里添加
public std::unary_function<T1,T1>
或public std::binary_function<T1,T2,T1>即可
本文来自CSDN博客,转载请标明出处: http://blog.csdn.net/thinkingmyl/archive/2009/08/17/4456419.aspx
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值