仿函数

来源:互联网 发布:通话软件源码 编辑:程序博客网 时间:2024/04/29 08:57

       所有的仿函数定义在头文件<functional>中。

1.定义及分析

       仿函数就是一个定义了operator()的对象。

class X {public://define "function call" operatorreturn-value operator() (arguments) const;...};//现在这个类对象就可以当做函数一样使用X fo;...fo(arg1, arg2); //call operator () for function object fo//等同于fo.operator() (arg1,arg2); //调用对象fo的operator()

凡是行为像函数,那么这个对象就是函数。仿函数就是这个意思,但是STL中为什么要用仿函数而不直接用函数呢?

       首先STL是一个有自己规则的框架,函数指针无法和STL其他组件搭配(配接器),产生更灵活的变化:

       仿函数应当有能力被函数配接器修饰,然后彼此合作形成一个整体。为了可配接仿函数需要定义自己的相应型别(和迭代器的型别的作用是一个含义)。由于STL只使用一元和二元仿函数,所以定义了两个class:unaru_function和binary_function。这两个类没有成员,只有一些型别定义。任何仿函数,只要依个人需求选择继承其中一个class,便自动拥有了那些相应型别,也就自动拥有了配接能力。

       其次仿函数相对于函数指针有其自身优点:

1、 仿函数是智能型函数

       就好比智能指针的行为像指针,其就可看作是一个指针。但是智能指针是定义的一个类对象,所以在具备指针功能的同时也有其他的能力。仿函数的能力也可以超越operator()。因为仿函数可以拥有成员函数和成员变量,这意味着仿函数拥有状态。另一个好处是可以在执行期初始化它们。

class AddValue {private:int theValue; //the value to addpublic:AddValue(int v) : theValue(v) {}void operator() (int& elem) const {elem += theValue;}};AddValue addx (x); //+xAddValue addy (y); //+yAddValue(10))//常量AddValue (*coll. begin())//变量

2、 仿函数都有自己的型别

       这就是泛型编程编写仿函数。

3、 仿函数通常比一般函数快

       就template的概念而言,由于更多细节在编译器就已确定,所以通常可能进行更好的最佳化。

2.预定义的仿函数

2.1算术类

       除了否定为一元,其他都为二元仿函数。

加法:plus<T>

减法:minus<T>

乘法:multiplies<T>

除法:divides<T>

求余:modulus<T>

否定:negate<T>

2.2关系运算类

       都是二元仿函数。

等于:equal_to<T>

不等于:not_equal_to<T>

大于:greater<T>

大于等于:greater_equal<T>

小于:less<T>

小于等于:less_equal<T>

2.3逻辑运算类

       与和或为二元仿函数,否为一元仿函数。

与:logical_and<T>

或:logical_or<T>

否:logical_not<T>

 

3.仿函数配接器

       仿函数配接器是配接器(仿函数、容器、迭代器)中最大的一部分。主要运用到的如以下所示:

绑定第一个参数为定值:bind1st(op,x)——效果op(x,param)

绑定第二个参数为定值:bind2nd(op,x)——效果op(param,x)

对一元仿函数逻辑取反:not1(op)——效果!op(param)

对二元仿函数逻辑取反:not2(op)——效果!op(param1,param2)

SGI版本特有的还有compose1和compose2,就是组合函数的意思:

compose1(op1,op2)——效果op1(op2())

       举例:

判定元素不小于12:bind2nd(greater_equal<int>(),12)或者not1(bind2nd(less<int>(),12))

对元素x执行(x+2)*3:compose1(bind2nd(multiplies<int>,3),bind2nd(plus<int>(),2))

      

       另外的函数配接器就是针对成员函数而设计的函数配接器:

mem_fun_ref(op)                 调用op,是某对象的一个const成员函数

men_fun(op)                        调用op,是某对象指针的一个const成员函数

注意,被men_fun_ref和men_fun调用的成员函数必须是const,C++标准库暂时不支持non-const成员函数提供函数配接器。

class Person {private:std::string name;public:...void print() const {std::cout << name << std::endl;}void printWithPrefix (std::string prefix) const {std::cout << prefix << name << std::endl;}};void foo (const std::vector<Person>& coll){using std::for_each;using std::bind2nd;using std::mem_fun_ref;//对各个元素调用成员函数printfor_each (coll.begin(), coll.end(),mem_fun_ref(&Person::print));//对各个元素调用成员函数printWithPrefix//-"person: "是传递的一个参数,所以使用了bind2ndfor_each (coll.begin(), coll.end(),bind2nd (mem_fun_ref (&Person::printWithPrefix),"person: "));}




原创粉丝点击