STL 函数对象的使用

STL 函数对象

1,重载函数调用操作符

函数对象:定义了调用操作符的类,其对象称为“函数对象”

STL中有大量的算法,这些算法是对SLT中的容器进行操作,算法需要函数对象作为参数因此使用STL算法的时候需要写函数对象。由于STL中的算法和容器都是用模板设计出来的,因此我们在写函数对象时也需要使用模板

函数对象相较于普通函数的优势在于,函数对象的定义本身是一个类,而类可以有数据成员,来保持自身状态,这是普通的函数不具备的功能。

2,函数对象的声明与使用

  • 普通模板函数

    template<typename elementType>
    void FuncDisplayElement(const elementType & element)
    {
    cout << element << ' ';
    }
  • 函数对象 :使用struct的原因:默认为public,而class中需要声明

    //这也是一个类, 它声明的对象就是函数对象
    struct absInt
    {
    //重载操作符:函数调用操作符
    int operator() (int val)
    {
        return  val < 0 ? -val : val;
    }
    };
    //使用模板
    template<typename elementType>
    struct DisplayElement
    {
    //存储状态
    int m_nCont;
    DisplayElement() // 构造函数,初始化类中的变量
    {
        m_nCont = 0;
    }
    void operator() (const elementType & element)
    {
        ++m_nCont;  //这里比普通的函数对象就多了一个计数调用了函数多少次的功能
        cout << element << ' ';
    }
    
    };
  • 使用

    /*普通函数对象的声明与使用*/
    int i = -42;
    absInt absObj;
    unsigned int ui = absObj(i); 
    
    /*STL中的函数对象与使用*/
    vector<int> a;            
    for (int i = 0; i < 10; ++i)
      a.push_back(i);                               //初始化一个vector
    
    DisplayElement<int> mResult;                  //声明一个函数对象
    mResult = for_each(a.begin(), a.end(),mResult);//将状态通过for_each的返回值赋值保留到mResult中
    cout << endl;
    cout << "number:" <<  mResult.m_nCont <//STL算法:
    //for_each算法:将处理前两个参数之间的所有数据,最后一个参数则为函数对象
  • 匿名对象的使用

    for_each(b.begin(), b.end(),DisplayElement<char>());
    //DisPlayElement在函数中直接使用的叫做匿名对象,匿名函数对象无法操作和得到其状态
  • for_each() 算法 :将处理前两个参数之间的所有数据,最后一个参数是指定的pred运算条件(用函数对象表示)

2,一元谓词

​ 函数只有一个参数,称为一元函数。函数对象只有一个参数,且返回值为布尔值时,为一元谓词。

  • 函数 :写一个函数,检查是否为某一个数的整数倍

    template<typename numberType>
    struct IsMultiple         //检查是否为某数的整数倍
    {
    numberType m_Divisor;   //被除数由a传递而来,这里传过来为3
    IsMultiple(const numberType & divisor)  //构造函数
    {
        m_Divisor = divisor;
    }
    
    bool operator() (const numberType & element) const
    {
        return ((element % m_Divisor) == 0);
    }
    };
  • 初始化一个向量作为操作数

    vector<int> vecIntegers;
    for (int i = 32; i < 101; ++i)
    {
      vecIntegers.push_back(i);
    }
  • find_if()算法 :根据指定的pred运算条件(以仿函数表示),循环查找[first,last)内的所有元素,找出第一个令pred运算结果true者。如果找到就返回一个InputIterator指向该元素,否则就返回迭代器last

    vector<int>::iterator iElement;
    IsMultiple<int> a(4);
    iElement = find_if(vecIntegers.begin(), vecIntegers.end(), a);
    // iElement = find_if(vecIntegers.begin(), vecIntegers.end(), IsMultiple(4));
    //匿名函数对象的使用
    if (iElement != vecIntegers.end())
      cout << "第一个四的整数倍是:" << *iElement << endl;

3,二元函数

​ 函数对象有两个参数,称为二元函数,函数对象有两个参数,且返回值为布尔值时,为二元谓词。

  • 二元函数示例 :创建一个类,来计算2个数的乘积。

    template<typename elementType>
    class CMultiply //乘法
    {
    public:
    elementType operator() (const elementType & elem1, const elementType & elem2)
    {
        return elem1 * elem2;
    }
    };
  • 初始化两个向量a,b,初始化存放乘积结果的mResult

    vector<int> a, b;
    for (int i = 0; i < 10; ++i)
      a.push_back(i);
    
    for (int i = 100; i < 110; ++i)
      b.push_back(i);
    
    vector<int> vecResult;
    vecResult.resize(10); //resize函数,分配空间让它与a,b一样大
  • transform()函数:

    transform(a.begin(), a.end(),b.begin(), vecResult.begin(), CMultiply());
    //transform的前两个参数指定了循环的范围,根据指定的运算方式与第三个参数运算,结果存到第四个参数中
    for (size_t i = 0; i < vecResult.size(); ++i)
      cout << vecResult[i] << endl;

4,二元谓词

  • 创建函数 :这里注意,这里的函数中的两个参数,一个是set集中本就有的,另一个是新插入的。根据这两个参数的大小来返回布尔值,以达到不区分大小写的目的

    //set中的string默认区分大小写
    //这里使用二元谓词实现不区分大小写查找对应字符串
    class CCompareStringNoCase
    {
    public:
    bool operator() (const string & str1, const string & str2) const
    {
        string str1LowerCase;
        str1LowerCase.resize(str1.size());  //新构建一个字符串保存备份并转化为小写字母
        transform(str1.begin(), str1.end(),str1LowerCase.begin(),::tolower);
        //transform函数,将字符串都转化为小写字母
    
        string str2LowerCase;
        str2LowerCase.resize(str1.size());  //新构建一个字符串保存备份并转化为小写字母
        transform(str2.begin(), str2.end(), str2LowerCase.begin(),::tolower);
          //transform函数,将字符串都转化为小写字母
    
        return(str1LowerCase < str2LowerCase);
    }
    
    };
  • 声明变量并插入数值

    set<string,CCompareStringNoCase> names;
    names.insert("Tina");
    names.insert("jim");
  • 使用find()函数 :查找set中的对应数据

    set<string, CCompareStringNoCase>::iterator iNameFound = names.find("tina");
    if(iNameFound != names.end())
      cout << "success " << *iNameFound <<  endl;
    else
      cout << "fail" << endl;

你可能感兴趣的:(STL 函数对象的使用)