美文网首页
函数对象(仿函数)

函数对象(仿函数)

作者: 呼吸秋千_6e9c | 来源:发表于2019-04-15 01:07 被阅读0次

    1.1 知识点

    • 函数对象概述
    • 预定义函数对象
    • 辅助函数对象
    • 适配器
    • 函数对象使用方法

    1.2 实验环境

    • g++
    • ubuntu 16.04

    1.3 代码获取

    可以通过以下链接获取本课程的源码内容,本次实验内容主要包含在文件Functional.h

    //获取代码
    wget http://labfile.oss.aliyuncs.com/courses/1166/mySTL.zip
    
    //解压文件到Code目录
    unzip -q mySTL.zip -d ./Code/
    
    
    二、函数对象概述

    函数对象是重载函数调用操作符的类的对象。即函数对象是行为类似函数的对象,又称仿函数,是一个能被当做普通函数来调用的对象。

    函数对象与函数指针相比,有两个优点:第一是编译器可以内联执行函数对象的调用;第二是函数对象内部可以保持状态。

    STL 中的众多算法,非常依赖于函数对象处理容器的元素。所以 STL 预定义了许多函数对象、谓词和适配器。

    三、预定义和辅助函数对象

    我们可以在 Functional.h 中预定义一些函数对象,以方便在以后的实验中直接调用。

    首先在 include 目录下创建 Functional.h。

    unary_function: 作为一元函数对象的基类,只定义了参数和返回值的类型
    template<class T>
    struct unary_function {
    typedef T argumant_type;
    typedef T result_type;
    };
    binary_function:作为二元函数基类,只定义了参数和返回值的类型
    template<class T>
    struct binary_function {
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef T result_type;
    };
    less:用于返回较小值
    template<class T>
    struct less{
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef bool result_type;

    result_type operator()(const first_argument_type& x, const second_argument_type& y){
        return x < y;
    }
    

    };
    equal_to: 判断是否相等
    template<class T>
    struct equal_to{
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef bool result_type;
    result_type operator()(const first_argument_type& x, const second_argument_type& y){
    return x == y;
    }
    };
    identity: 验证同一性
    template <class T>
    struct identity : public unary_function<T> {
    const T& operator()(const T& x) const {return x;} //函数调用操作符
    };
    select1st: 返回键值,在 map 中会用到
    template <class T>
    struct select1st : public unary_function<T, typename T::first_type> {
    const typename T::first_type& operator()(const T& x) const {return x.first;}

    四、适配器

    函数对象适配器本质上任然是一个函数;函数对象适配器提供了对函数对象或者普通函数的操作,使其能够根据我们的需求来修改函数对象或者普通函数的功能。

    使用函数对象适配器的步骤:

    (1)首先让自定义的函数对象 public 继承一个父类。这里有两个选择:binary_function 和 unary_function。如果有两个参数选择前者。

    (2)定义一个函数对象作为参数传入函数对象适配器。常见的函数对象适配器有:

    绑定适配器 bind1st bind2nd (bind1st 绑定第一个参数, bind2nd 绑定第二个参数)
    取反适配器 not1 not2 (not1 作用于一元函数对象,not2 作用于二元函数对象)
    普通函数适配器 ptr_fun
    作用于类中方法的适配器 mem_fun mem_fun_ref
    (3)加 const

    五、实例测试

    我们在上面讲了预定义函数对象和适配器,在下面我们就来演示预定义函数和适配器的搭配。我们在 Test 文件夹下建立 functionaltest.cpp,在这里需要用到 vector 容器来测试,关于Vector 容器的内容,我们将在后面的实验中给大家讲解,这里我们直接使用 Vector.h的内容。该文件可以通过下载课程源码找到。

    #include <iostream>
    #include "Vector.h"
    #include "Functional.h"
    
    using namespace std;
    
    class compare:public binary_function<int,int,bool>{//用于接收两个参数
    public:
        bool operator()(int i, int num) const {
            return i > num;
        }
    };
    
    class comparetonum:public unary_function<int,bool>{//用于接收一个参数
    public:
        bool operator()(int i) const {
            return i > 5;
        }
    };
    
    void print(int i,int j)//普通函数对象
    {
        if (i > j){
            cout << i << " ";
        }
    }
    
    int main(){
    
        mySTL::vector <int> vec;
        for (int i = 0; i < 10; i++)
        {
            vec.push_back(i + 1);
        }
    
        mySTL::vector<int>::iterator it = find_if(vec.begin(), vec.end(), bind2nd(compare(),6));//找出大于6的第一个数
        if (it == vec.end())
        {
            cout << "cannot find the number!" << endl;
        }
        else
        {
            cout << "find num: " << *it << endl;
        }
    
        mySTL::vector<int>::iterator rit = find_if(vec.begin(), vec.end(), not1(comparetonum()));  //取反适配器的用法,找出小于5的第一个数
        if (rit == vec.end())
        {
            cout << "cannot find the number!" << endl;
        }
        else
        {
            cout << "find num: " << *rit << endl;
        }
    
        mySTL::vector<int> vec1;
        for (int i = 0; i < 10; i++)
        {
            vec1.push_back(i);
        }
    
        cout<<"The num larger than 5: ";
        mySTL::for_each(vec1.begin(), vec1.end(), bind2nd(ptr_fun(print),5)); //使用ptr_fun将普通函数转换为函数对象,然后给函数对象绑定参数。
        cout << endl;
    
        return 0;
    }
    
    

    执行命令:

    g++ functionaltest.cpp -std=c++11 -o functionaltest -I ../include
    
    

    相关文章

      网友评论

          本文标题:函数对象(仿函数)

          本文链接:https://www.haomeiwen.com/subject/wgzewqtx.html