13.7.3 函数适配器

    在前面介绍的代码13.17中已经使用过函数适配器“bind2nd(lt,3)”,这是绑定适配器的一种,此外,还有否定器和函数指针适配器。

    1.绑定器

    诸如“bind2nd(lt,3)”之类的绑定器可以对函数对象it进行修改操作,将it的参数绑定在某个特定值上,如代码13.17中便是把it函数对象的第2个参数绑定为3,这使得二元函数对象可转换成一元函数对象,使得在某些场合下不能用的函数变得能用。STL提供了以下两个绑定器。

    ❑bind1st(函数对象,指定值)

    将指定值绑定在函数对象的第1个参数上。

    ❑bind2nd(函数对象,指定值)

    将指定值绑定在函数对象的第2个参数上。

    2.否定器

    STL中提供了否定器用于逆转函数对象的真伪值,因此要求函数对象是断言,STL提供了以下两个否定器。

    ❑not1

    用以逆转一元断言。

    ❑not2

    用以逆转二元断言。

    例如代码13.19所示,它是在代码13.17的基础上修改而来的。

    代码13.19 否定器的使用Negator


    <————————————文件名:example1319.cpp——————————————-> 01 #include<iostream> 02 #include<algorithm>//使用for_each函数要包含的头文件 03 #include<functional>//使用less<>类模板要用的头文件 04 #include<vector> 05 using namespace std; 06 typedef vector<int>VI; 07 typedef VI:iterator VIP; 08 int main() 09 { 10 int sz[]={1,2,3,4,5,6}; 11 VI ob(sz,sz+6); 12 less<int>lt;//创建less<int>类函数对象 13 replace_if(ob. begin(),ob.end(),not1(bind2nd(lt,3)),7); 14 for(VIP v=ob. begin();v!=ob.end();v++) 15 { 16 cout<<(*v)<<""; 17 } 18 cout<<endl; 19 return 0; 20 }

    输出结果如下所示。


    1 2 7 7 7 7

    【代码解析】对比代码13.19和代码13.17的输出结果可以很容易地体会到否定器的用法,在代码第13行中使用“replace_if”语句,将大于等于3(less<int>,即小于3的反)的元素都被替换为7。

    3.成员函数适配器

    如果某个容器中存储的元素是某个类的对象,该如何调用对象的函数呢?有以下的解决方法,Ex为类名,vector<Ex>ob为容器对象,假设void do()是Ex类中定义的成员函数,如下所示。


    for(vector<Ex>:size_type i=0;i<ob.size();i++) ob[i]->Do();当然,也可以用iterator,如下所示。 for(vector<Ex>:iteratorit=ob.begin();it!=ob.end();it++) (*it)->Do();实际上,STL中不推荐自己书写循环结构,因此一种替代性的思路便是使用for_each()结构,为此必须书写一个函数,如下所示。 void DoInterface(Ex&ex) { ex.do(); }此时,只要使用如下代码即可实现每个元素都调用该成员函数。 for_each(ob.begin(),ob.end(),DoInterface);实际上,借助STL提供的成员函数适配器(mem_fun_ref和mem_fun)即可实现对元素对象内成员函数的直接调用,如下所示。 for_each(ob.begin(),ob.end(),mem_fun_ref(Ex:do()));

    mem_fun_ref和mem_fun的区别在于当容器中存放的是对象实体的时候用mem_fun_ref,当容器中存放的是对象的指针的时候用mem_fun。