C++ STL仿函数适配器

目录

0适配器

1适配器概念的引出—联结(bind)函数

2取反适配器

3函数指针适配器

4成员函数适配器 


0适配器

适配器模式把一个类的接口变换成客户端所期待的另一种接口

从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作 

注意:适配器提供迭代器

以下将介绍几种常用的仿函数适配器

1联结(bind)

通过bind,我们仿函数与参数进行绑定,可实现算法所需的条件判断功能,例如判断小于12的元素时,可使用bind2nd(less(),12),就可以达到目的。

2否定(negate)

这里就是取反的操作,例如not1(bind2nd(less(),12)),就可判断不小于12的元素。

3组合(compose)

当算法的判断条件需要进行一些复杂的数学运算时,即可采用这种适配操作。例如对每个元素v进行(v+2)*3操作,就可表示为compose1(bind2nd(multiplies(),3),bind2nd(plus(),2))。  

4一般函数适配器 

一般函数可以当做仿函数供STL算法使用,但无配接能力,需要将其包装成仿函数,其原理就是在仿函数的运算符()内执行其所包装的函数即可。 

5成员函数适配器  

这里将成员函数包装成仿函数,从而可使用成员函数搭配各种泛型算法。当容器内存储的是对象的实体时,需使用mem_fun_ref进行适配;当容器内存储的是对象的指针时,需使用mem_fun进行适配。

分来来源:

7、【C++ STL】适配器https://www.cnblogs.com/Long-w/p/9830192.html

使用适配器要注意:

1:继承

2:括号重载:一定要是常函数 

1适配器概念的引出—联结(bind)函数

打印vector中的元素

    vector<int> v;
    v.push_back(1);
    v.push_back(4);
    v.push_back(3);
    v.push_back(6);
    v.push_back(7);
    sort(v.begin(),v.end(),greater<int>());
    for_each(v.begin(),v.end(),[](int val){cout<<val<<endl;});

以上是使用函数指针,下面使用函数对象。

函数对象:

class Print
{
public:
    void operator()(int v)
    {
        qDebug()<<v;
    }
};
    vector<int> v;
    v.push_back(1);
    v.push_back(4);
    v.push_back(3);
    v.push_back(6);
    v.push_back(7);
    sort(v.begin(),v.end(),greater<int>());
    for_each(v.begin(),v.end(),Print());

 

现在有如下要求,打印每个元素的时候,增加100

使用适配器

类 

class Print:public binary_function<int,int,void>
{
public:
    void operator()(int v,int DeLta) const
    {

        qDebug()<<"v+DeLta:"<<v+DeLta
               <<"v:"<<v
              <<"DeLta:"<<DeLta;

    }
};

具体操作: 

    vector<int> v;
    v.push_back(1);
    v.push_back(4);
    v.push_back(3);
    v.push_back(6);
    v.push_back(7);
    sort(v.begin(),v.end(),greater<int>());
    int DeLta = 10;
    qDebug()<<"增量DeLta"<<DeLta;
    qDebug()<<"bind2nd:";
    for_each(v.begin(),v.end(),bind2nd(Print(),DeLta));

    qDebug()<<"bind1st:";
    for_each(v.begin(),v.end(),bind1st(Print(),DeLta));

输出:

使用bind适配器,有四点非常重要

1需要头文件

#include<algorithm>
#include<functional>

2类继承

class Print:public binary_function<int,int,void>

binary_function<参数类型1,参数类型2,返回值类型> 

3常函数

重载函数,需要定义为常函数

    void operator()(int v,int DeLta) const

4增加适配器 

    for_each(v.begin(),v.end(),bind2nd(Print(),DeLta));

    for_each(v.begin(),v.end(),bind1st(Print(),DeLta));

bind2nd和bind1st有区别,参数的位置和含义不同,所以需要注意,区别看上面的输出

绑定适配器参数必须函数对象不能函数指针

2取反适配器

一元取反:定义函数对象

class GreaterThanFive
{
public:
    bool operator()(int v)
    {
        return v>5;
    }
};

 具体操作:

    vector<int> v;
    v.push_back(1);
    v.push_back(4);
    v.push_back(3);
    v.push_back(6);
    v.push_back(7);

    vector<int>::iterator it = find_if(v.begin(),v.end(),GreaterThanFive());
    if(it!=v.end())
    {
        qDebug()<<"找到了:"<<*it;
    }
    else
    {
        qDebug()<<"没有找到";
    }

进行取反适配器的使用,增加必要的关键字,继承类

class GreaterThanFive:public unary_function<int,bool>
{
public:
    bool operator()(int v) const
    {
        return v>5;
    }

};

具体操作: 

    vector<int> v;
    v.push_back(1);
    v.push_back(4);
    v.push_back(3);
    v.push_back(6);
    v.push_back(7);

    vector<int>::iterator it = find_if(v.begin(),v.end(),not1(GreaterThanFive()));
    if(it!=v.end())
    {
        qDebug()<<"找到了:"<<*it;
    }
    else
    {
        qDebug()<<"没有找到";
    }

同样,还可以通过下面的方法,进行操作:使用两个适配器加上内建函数

    vector<int>::iterator it = find_if(v.begin(),v.end(),not1(bind2nd(greater<int>(),5)));

使用not适配器,有四点非常重要

1需要头文件

#include<algorithm>
#include<functional>

2类继承

class GreaterThanFive:public unary_function<int,bool>

继承类unary_function<输入数据类型,返回值类型> 

3常函数

重载函数,需要定义为常函数

bool operator()(int v) const

4增加适配器 

vector<int>::iterator it = find_if(v.begin(),v.end(),not1(GreaterThanFive()));

3函数指针适配器

接口:

void print_function(int v,int DeLta)
{
    qDebug()<<"v+DeLta:"<<v+DeLta
           <<"v:"<<v
          <<"DeLta:"<<DeLta;
}

具体操作: 

    vector<int> v;
    v.push_back(1);
    v.push_back(4);
    v.push_back(3);
    v.push_back(6);
    v.push_back(7);
    int DeLta = 10;
    qDebug()<<"增量DeLta"<<DeLta;
    qDebug()<<"bind2nd:";
    for_each(v.begin(),v.end(),bind2nd(ptr_fun(print_function),DeLta));

因为绑定适配器(bind)参数必须是函数对象,所以可以把函数指针转化为函数对象。

以下的两个适配器不需要对接口函数进行多余的操作,以下两个适配器主要是将函数指针成员函数指针变成函数对象

4成员函数适配器 

自定义类型及接口详情 

class Person
{
public:
    Person(const int num,const QString name)
    {
        member_num = num;
        member_name = name;
    }
    void showPerson();
    int member_num;
    QString member_name;
};
void Person::showPerson()
{
    qDebug()<<"p.member_name:"<<member_name<<"p.member_num:"<<member_num;
}

 具体操作:

    Person p1(1,"123");
    Person p2(2,"223");
    Person p3(3,"323");
    Person p4(4,"423");
    Person p5(5,"523");
    Person p6(6,"623");

    vector<Person> v;
    v.push_back(p1);
    v.push_back(p2);
    v.push_back(p3);
    v.push_back(p4);
    v.push_back(p5);
    v.push_back(p6);

    for_each(v.begin(),v.end(),mem_fun_ref( Person::showPerson ));

输出: 

此处是将成员函数变成函数指针。

发布了85 篇原创文章 · 获赞 11 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_41605114/article/details/105068323