• 《STL源代码剖析》学习笔记系列之七、八——仿函数和配接器


    1、 仿函数

    仿函数又名函数对象。具有函数性质的对象。就是传入一些參数。然后对參数进行某些运算,然后返回一个值。

    为了可以使行为类似函数,须要在类别定义中必须自己定义function call 运算子operator()。

    仿函数有例如以下几类:算术类仿函数(plus<T>、minus<T>)关系运算类仿函数(equal_to<T>、less<T>)逻辑运算类仿函数(logical_and<T>、logical_or<T>、logical_not<T>)证同、选择、投射。

    1.1、可配接的关键

    可配接指的是可以在类原有的基础上扩展成另外一个类。仿函数为此定义了两个类,分别代表一元仿函数和二元仿函数。

    之后的不论什么仿函数,依据功能需求选择当中一个类继承。详细代码例如以下:

    一元仿函数

    template<class Arg, classResult>

    struct unary_function

    {

       typedef Arg argument_type;

       typedef Result result_type;

    };

     

    template<class T>

    struct negate:publicunary_function<T,T>

    {

       T operator()(const T& x) const {return -x;}

    };

    二元仿函数

    template<class Arg1,classArg2,class Result>

    struct binary_function

    {

       typedef Arg1 first_argument_type;

       typedef Arg2 second_argument_type;

       typedef Result result_type;

    };

     

    template<class T>

    struct plus:publicbinary_function<T,T,T>

    {

       T operator()(const T& x,const T& y) const {return x+y;}

    };

    2、配接器

    配接器类似于转换器,它是一种设计模式,在原有的类型基础上扩展成为另外一个接口,使原本由于接口不兼容而不能合作的类型能够一起工作。

    配接器分类例如以下:function adapter(改变仿函数接口)、container adapter(改变容器接口)、iterator adapter(改变迭代器接口)。

    2.1     container adapter

    最明显的样例就是stack和queue, 直接上代码,一看便知:

    template<class T,classSequence=deque<T>>

    class stack

    {

         protected:

                Sequence c; //底层容器採用 deque

    }

     

    template<class T.classSequence=deque<T>>

    class queue

    {

         protected:

            Sequence c;

    }

    由上可知,class stack和class queue均以deque为底层容器。然后通过封主deque全部对外接口,仅仅开放符合stack或queue原则的几个函数,所以我们称stack和queue是个配接器,一个作用于容器之上的配接器。

    2.2     iterator adapter

    书中针对迭代器适配器分三类进行描写叙述:insert iterator、 reverseiterator、iostream iterator。后两种在实现技巧和理解上都相对复杂一些。通过实例来分析吧,代码例如以下:

    int main()

    {

    1    ostream_iterator<int> outite(cout," ");

    2    int ia[]={0,1,2,3,4,5};

    3    deque<int> id(ia,ia+6);

    4    copy(id.begin(),id.end(),outite);

    5    cout<<endl;  // 0 1 23 4 5

    6    copy(ia+1,ia+2,front_inserter(id));

    7    copy(id.begin(),id.end(),outite);

    8    cout<<endl;  //1 0 12 3 4 5

    9    deque<int>::iterator ite=find(id.begin(),id.end(),4);

    10  reverse_iterator<deque<int>::iterator>rite(ite)

    11   cout<<*ite<<endl; //4

    12  cout<<*rite<<endl; //3

    }

    由上可知。上述第1行代码。採用了iostream iteratoradapter将迭代起绑定到cout对象,组成一个ostream_iterator。拥有输出功能。

    第6行代码中front_inserter(id)是个辅助函数,方便client使用insert_iterator。调用该函数后实际产生一个对象迭代器适配器对象:

    front_inserter_iterator<container>(x)。第10行代码中,通过reverse iterator迭代器配接器,转换了迭代器的方向,可是须要注意的是迭代器被逆转,尽管实体位置不变。即指针所在的位置不变。可是其所指的实体位置发生的改变,一个指向右,一个指向左。例如以下图所看到的:

                    

    2.3     function adapter

    该部分是全部配接器中数量最庞大的一个族群。主要是通过对仿函数进行配接操作。组成更加丰富的表达式,简单的样例例如以下:

    not1(bind2nd(less<int>(),12))

    上式表述的是一个不小于12的表达式,当中less<int>()为仿函数,通过bind2nd这个配接器器辅助函数的操作转换成第二种仿函数。

    另外须要补充的是用户函数指针的ptr_fun配接器和用户成员函数指针的mem_funmen_fun_ref。通过配接器操作可以将一般函数和成员函数当做仿函数使用,并传给STL算法。

     

  • 相关阅读:
    VC 读取服务器上的文件(HTTP方式) [转]
    ActiveX控件打包成Cab置于网页中自动下载安装 [转]
    C# 使用xenocode混淆加密【转】
    jenkins插件安装失败更改插件源
    jenkins调用shell脚本 输出带颜色字体
    Centos7 搭建最新 Nexus3 Maven 私服
    jenkins构建java项目找不到命令mvn,java的解决方法
    如何在 Linux 中找到你的 公网IP 地址
    CentOS 7安装Zabbix 3.4
    Linux常见服务器——DHCP服务器的搭建
  • 原文地址:https://www.cnblogs.com/jhcelue/p/6808259.html
Copyright © 2020-2023  润新知