STL(内建函数对象,函数对象适配器 )

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_42754132/article/details/100063836

4.3 内建函数对象

STL内建了一些函数对象。分为:算数类函数对象,关系运算类函数对象,逻辑运算类仿函数。这些仿函数所产生的对象,用法和一般函数完全相同,当然我们还可以产生无名的临时对象来履行函数功能。使用内建函数对象,需要引入头文件 #include<functional>

 

  1. 6个算数类函数对象,除了negate是一元运算,其他都是二元运算。

template<class T> T plus<T>//加法仿函数

template<class T> T minus<T>//减法仿函数

template<class T> T multiplies<T>//乘法仿函数

template<class T> T divides<T>//除法仿函数

template<class T> T modulus<T>//取模仿函数

template<class T> T negate<T>//取反仿函数

 

  1. 6个关系运算类函数对象,每一种都是二元运算。

template<class T> bool equal_to<T>//等于

template<class T> bool not_equal_to<T>//不等于

template<class T> bool greater<T>//大于

template<class T> bool greater_equal<T>//大于等于

template<class T> bool less<T>//小于

template<class T> bool less_equal<T>//小于等于

 

  1. 逻辑运算类运算函数,not为一元运算,其余为二元运算。

template<class T> bool logical_and<T>//逻辑与

template<class T> bool logical_or<T>//逻辑或

template<class T> bool logical_not<T>//逻辑非

 

内建函数对象举例:

//取反仿函数

void test01()

{

    negate<int> n;

    cout << n(50) << endl;

}

 

//加法仿函数

void test02()

{

    plus<int> p;

    cout << p(10, 20) << endl;

}

 

//大于仿函数

void test03()

{

    vector<int> v;

    srand((unsigned int)time(NULL));

    for (int i = 0; i < 10; i++){

       v.push_back(rand() % 100);

    }

 

    for (vector<int>::iterator it = v.begin(); it != v.end(); it++){

       cout << *it << " ";

    }

    cout << endl;

    sort(v.begin(), v.end(), greater<int>());

 

    for (vector<int>::iterator it = v.begin(); it != v.end(); it++){

       cout << *it << " ";

    }

    cout << endl;

 

}


 13 内建函数对象
    取反
    加法
    排序
    大于 greater<int>()

#include <iostream>
#include <functional>//内建函数对象的头文件
#include <vector>
#include <algorithm>
using namespace std;

//template<class T> T negate<T>//取反仿函数
void test01(){

    negate<int>n;
    cout<<n(10)<<endl;//直接使用
//加法 template<class T> T plus<T>//加法仿函数
    plus<int> p;
    cout<<p(1,1)<<endl;

}
//template<class T> bool greater<T>//大于
void test02(){
    vector<int>v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);       //默认源码是less<>()
  sort(v.begin(),v.end(),greater<int>());//匿名对象 降序排序
  for_each(v.begin(),v.end(),[](int val){cout<<val<<endl;});

}

int main(){
    //test01();
    test02();
    return 0;
}

 

3.1.4 函数对象适配器

//函数适配器bind1st bind2nd

//现在我有这个需求 在遍历容器的时候,我希望将容器中的值全部加上100之后显示出来,怎么做

//我们直接给函数对象绑定参数 编译阶段就会报错

//for_each(v.begin(), v.end(), bind2nd(myprint(),100));

//如果我们想使用绑定适配器,需要我们自己的函数对象继承binary_function 或者 unary_function

//根据我们函数对象是一元函数对象 还是二元函数对象

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

{

public:

    void operator()(int v1,int v2) const

    {

        cout << "v1 = : " << v1 << " v2 = :" <<v2  << " v1+v2 = :" << (v1 + v2) << endl;  

    }

};

//1、函数适配器

void test01()

{

    vector<int>v;

    for (int i = 0; i < 10; i++)

    {

        v.push_back(i);

    }

    cout << "请输入起始值:" << endl;

    int x;

    cin >> x;

 

    for_each(v.begin(), v.end(), bind1st(MyPrint(), x));

    //for_each(v.begin(), v.end(), bind2nd( MyPrint(),x ));

}

//总结:  bind1st和bind2nd区别?

//bind1st 将参数绑定为函数对象的第一个参数

//bind2nd 将参数绑定为函数对象的第二个参数

//bind1st bind2nd将二元函数对象转为一元函数对象

 

 

class GreaterThenFive:public unary_function<int,bool>

{

public:

    bool operator ()(int v) const

    {

        return v > 5;

    }

};

 

//2、取反适配器

void test02()

{

    vector <int> v;

    for (int i = 0; i < 10;i++)

    {

        v.push_back(i);

    }

   

// vector<int>::iterator it =  find_if(v.begin(), v.end(), GreaterThenFive()); //返回第一个大于5的迭代器

//  vector<int>::iterator it = find_if(v.begin(), v.end(),  not1(GreaterThenFive())); //返回第一个小于5迭代器

    //自定义输入

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

    if (it == v.end())

    {

        cout << "没找到" << endl;

    }

    else

    {

        cout << "找到" << *it << endl;

    }

 

    //排序  二元函数对象

    sort(v.begin(), v.end(), not2(less<int>()));

    for_each(v.begin(), v.end(), [](int val){cout << val << " "; });

 

}

//not1 对一元函数对象取反

//not2 对二元函数对象取反

 

void MyPrint03(int v,int v2)

{

    cout << v + v2<< " ";

}

 

//3、函数指针适配器   ptr_fun

void test03()

{

    vector <int> v;

    for (int i = 0; i < 10; i++)

    {

        v.push_back(i);

    }

    // ptr_fun( )把一个普通的函数指针适配成函数对象

    for_each(v.begin(), v.end(), bind2nd( ptr_fun( MyPrint03 ), 100));

}

 

 

//4、成员函数适配器

class Person

{

public:

    Person(string name, int age)

    {

        m_Name = name;

        m_Age = age;

    }

 

    //打印函数

    void ShowPerson(){

        cout << "成员函数:" << "Name:" << m_Name << " Age:" << m_Age << endl;

    }

    void Plus100()

    {

        m_Age += 100;

    }

public:

    string m_Name;

    int m_Age;

};

 

void MyPrint04(Person &p)

{

    cout << "姓名:" <<  p.m_Name << " 年龄:" << p.m_Age << endl;

 

};

 

void test04()

{

    vector <Person>v;

    Person p1("aaa", 10);

    Person p2("bbb", 20);

    Person p3("ccc", 30);

    Person p4("ddd", 40);

    v.push_back(p1);

    v.push_back(p2);

    v.push_back(p3);

    v.push_back(p4);

 

    //for_each(v.begin(), v.end(), MyPrint04);

    //利用 mem_fun_ref 将Person内部成员函数适配

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

// for_each(v.begin(), v.end(), mem_fun_ref(&Person::Plus100));

// for_each(v.begin(), v.end(), mem_fun_ref(&Person::ShowPerson));

}

 

void test05(){

 

    vector<Person*> v1;

    //创建数据

    Person p1("aaa", 10);

    Person p2("bbb", 20);

    Person p3("ccc", 30);

    Person p4("ddd", 40);

 

    v1.push_back(&p1);

    v1.push_back(&p2);

    v1.push_back(&p3);

    v1.push_back(&p4);

 

    for_each(v1.begin(), v1.end(), mem_fun(&Person::ShowPerson));

}

 

//如果容器存放的是对象指针,  那么用mem_fun

//如果容器中存放的是对象实体,那么用mem_fun_ref

 

    
 14 适配器
  函数适配器
  0~9加起始值 进行输出 用户提供起始值
  bind2nd 绑定
  继承 binary_function(参数类型一,参数类型二,返回值类型)
  加 const 修饰operator()
  
  取反适配器  not1一元 找出>/<5 
  not2 二元 排序 not2(less<int>()) 从大到小 greater<int>()
  
  普通函数指针适配
  ptr_fun
 
 成员函数适配
  //如果容器存放的是对象指针,  那么用mem_fun
  //如果容器中存放的是对象实体,那么用mem_fun_ref
 

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>  //bind2nd
#include <string>
using namespace std;

class myPrint:public binary_function<int,int,void>{
public:
    void operator()(int value,int start)  const { //加const 不让修改
        cout<<"v=="<<value<<"start=="<<start<<"  value+start="<<value+start<<endl;
    }
};

void test01(){
    vector<int>v;
    for(int i=0;i<10;i++){
        v.push_back(i);
    }

    int num;
    cout<<"请输入一个起始值"<<endl;
    cin>>num;

//第一步:绑定数据 bind2nd
//第二步:继承类  binary_function<参数类型一,参数类型二,返回值类型> //对于二元
//第三步:加const修饰operator()

//适配器的功能,把一个参数变成两个参数



    for_each(v.begin(),v.end(),bind2nd(myPrint(),num));  //start是100(假定输入100)
    /*
v==0start==100  value+start=100
v==1start==100  value+start=101
v==2start==100  value+start=102
v==3start==100  value+start=103
v==4start==100  value+start=104
v==5start==100  value+start=105
v==6start==100  value+start=106
v==7start==100  value+start=107
v==8start==100  value+start=108
v==9start==100  value+start=109
*/

cout<<endl<<"-----------------------------"<<endl;
for_each(v.begin(),v.end(),bind1st(myPrint(),num));//数据反了过来 start 是 0......9
    /*
v==100start==0  value+start=100
v==100start==1  value+start=101
v==100start==2  value+start=102
v==100start==3  value+start=103
v==100start==4  value+start=104
v==100start==5  value+start=105
v==100start==6  value+start=106
v==100start==7  value+start=107
v==100start==8  value+start=108
v==100start==9  value+start=109
*/

 //需求:
//十个数 都加100 输出
//用户提供数据 加完再输出

}


class greaterThanFive : public unary_function<int,bool>{//一元取反
public:
    bool operator()(int v) const {
        return v>5;
    }
};


//取反适配器(一元取反)

void test02(){
    vector<int>v;
    for(int i=0;i<10;i++){
        v.push_back(i);
    }

    //查找大于5的数字
    //需求改为 找小于5的数字
    //not1()一元取反
/*
   vector<int>::iterator pos=find_if(v.begin(),v.end(),not1(greaterThanFive()));
   if(pos!=v.end()){
       cout<<"the number more than 5 is:"<<*pos<<endl;

   } else
   {
       cout<<"没找到"<<endl;
   }
*/

    //高端操作              和上边等价  找一个大于5的数  绑在一起才能输出  再做取反  greater 是
    //内建函数对象
    vector<int>::iterator pos=find_if(v.begin(),v.end(),not1(bind2nd(greater<int>(),5)));
    if(pos!=v.end()){
        cout<<"the number more than 5 is:"<<*pos<<endl;

    } else
    {
        cout<<"没找到"<<endl;
    }

}
//一元 取反适配器 not1()
//继承unary_function<参数类型1,返回值类型>
//const 修饰







void myPrint03(int val,int start){
    cout<<val+start<<endl;
}

//函数指针适配器
void test03(){
    vector<int>v;
    for(int i=0;i<10;i++){
        v.push_back(i);
    }
    //将普通函数指针(改)适配为函数对象
    //ptr_fun
    //好处 不用做继承 不用const

    for_each(v.begin(),v.end(),bind2nd(ptr_fun(myPrint03),100));//函数不加小括号

}

//成员函数适配器

class Person{
public:
    Person(string name,int age){
        this->m_Age=age;
        this->m_Name=name;
    }
    string m_Name;
    int    m_Age;

    void showPerson(){
         cout<<"成员函数中:"<<endl;
         cout<<"name:"<<m_Name<<"    age:"<<m_Age<<endl;
    }

    void plusAge(){
        this->m_Age=this->m_Age+100;
    }


};

void myPrintPerson(Person &p){
    cout<<"name:"<<p.m_Name<<"    age:"<<p.m_Age<<endl;
}



void test04(){
    Person p1("aa",132);
    Person p2("bb",12);
    Person p3("cc",15);
    Person p4("dd",13);
    Person p5("ee",123);
vector<Person>v;
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
v.push_back(p5);
//  for_each(v.begin(),v.end(),myPrintPerson);

//成员函数适配器
//mem_func_ref
for_each(v.begin(),v.end(),mem_fun_ref(&Person::showPerson));//格式就是这个
for_each(v.begin(),v.end(),mem_fun_ref(&Person::plusAge));
for_each(v.begin(),v.end(),mem_fun_ref(&Person::showPerson));//格式就是这个
//好处 成员方法  批量操作


}

int main(){
//test01();
//test02();
 //   test03();
   test04();
    return 0;
}

(本笔记内容整理自网络资源,侵删)

猜你喜欢

转载自blog.csdn.net/qq_42754132/article/details/100063836