函数对象(functional)

   来自STL中的概念:如果f是一个function object,则可以将operator()作用于f身上。

调用函数对象时构造函数和operator()执行顺序

  1. 首先执行构造函数,构造出一个匿名对象
  2. 然后在执行operator(),产生函数行为
#include <iostream>
#include <vector>
#include <algorithm>
#include <string.h>
#include <iterator>
using namespace std;

class F1
{
    public:
        F1(string t):s1(t)
        {
            cout<<" 带参构造函数"<<endl;
        }
        F1()
        {
            cout<<" 无参构造函数"<<endl;
        }
        bool operator()(string s)
        {
            cout<<" operator()函数"<<endl;
            return strcmp(s.c_str(),s1.c_str());
        }
    private:
        string s1;
};
int main()
{
    vector<string> vs{"hello"," ","word","!","how"," ","you","."};
    //1.F1 f1("you");被解析为f1.operator(arg);
    F1 f1("you");
    remove_copy_if(vs.begin(),vs.end(),ostream_iterator<string>(cout,"\n"),f1);
    cout<<"****************************************"<<endl;
    //2.
    remove_copy_if(vs.begin(),vs.end(),ostream_iterator<string>(cout,"\n"),F1("you"));
    cout<<"****************************************"<<endl;
    //3.
    F1()("hello");//这是一个函数调用的行为 
    return 0;
}
  1. F1 f1("you");被解析为f1.operator(arg);
  2. f1("you")是调用仿函数的operator();

函数对象与指针区别

  1. 指针当参数被调用时形参要写成 指针函数如:T (*ptr)(T x, T y);
  2. 函数对象调用时定一个模板参数即可如:
    template <typename InputIterator, typename T, typename FunObject>
    inline T accumulate(InputIterator first, InputIterator last, T init, FunObject object) {//函数对象
        while (first != last) {
            init = object(init, *first);
            ++first;
        }
    
        return init;
    }
    template < typename T>
    class Test {
        public:
        T operator()(const T& x, const T& y) {
            return x + y;
        }
    };
    accumulate(&a[0], &a[5], 0, Test<int>());

     

  3. 数指针的调用,我们的电脑需要做很多工作,比如说保存当前的寄存器值,传递参数,返回值,返回到函数调用地方继续执行等

总结

  1. 函数对象是一种带状态的函数,函数对象可以带成员变量和成员函数
  2. 函数对象有自己的类型
  3. 函数对象通常比函数的速度快,通常许多细节在编译期间都能确定
  4. 声明成员函数operator()要写成 return_value operator() (args...) const,因为在声明一个平常的class时影响不大,但是如果要以by const reference非(by value)的方式传递function object时,那么operator()要求是const

STL中的函数对象

 

函数对象模板类名辅助函数名说明
unary_composecompose1unary_compose(const AdaptableUnaryFunction1& f,
              const AdaptableUnaryFunction2& g);

生成一个一元函数对象,操作为“f(g(x))”;vc6/7自带stl没有定义。

binary_composecompose2binary_compose(const AdaptableBinaryFunction& f, 
               const AdaptableUnaryFunction1& g1, 
               const AdaptableUnaryFunction1& g2);

生成一个二元函数对象,操作为“f(g1(x), g2(x))”;vc6/7自带stl没有定义。

unary_negatenot1unary_negate(const AdaptablePredicate& pred);

一元谓词取非。

binary_negatenot2binary_negate(const AdaptableBinaryPredicate& pred);

二元谓词取非。

binder1stbind1stbinder1st(const AdaptableBinaryFunction& F,
          AdaptableBinaryFunction::first_argument_type c);

把二元函数对象的第一个参数绑定为c,生成一个一元函数对象。

binder2nd bind2ndbinder2nd(const AdaptableBinaryFunction& F,
          AdaptableBinaryFunction::second_argument_type c);

把二元函数对象的第二个参数绑定为c,生成一个一元函数对象。

pointer_to_unary_functionptr_fun把普通全局函数或全局函数指针(只能有1个或2个参数)转换成函数对象。

ptr_fun有两个原型分别生成pointer_to_unary_function对象和pointer_to_binary_function对象。

pointer_to_binary_function
mem_fun_tmem_fun把某个类的成员函数(只能有0个或1个参数,因为类成员函数的第一个参数已定义为this指针)转换成函数对象。

mem_fun有两个原型分别生成mem_fun_t对象(是个一元函数对象)和mem_fun1_t对象(是个二元函数对象)。

mem_fun1_t
mem_fun_ref_tmem_fun_ref类似mem_fun,区别如下:

struct T{
     print(){}
};

list<T*> lstT;
for_each(lstT.begin(),lstT.end(),mem_fun(&T::print));

list<T> lstT;
for_each(lstT.begin(),lstT.end(),mem_fun_ref(&T::print));

mem_fun1_ref_t
   

算术运算

  他们都继承与binary_function<arg1,arg2,result>,binary_function是一个基本的二元函数对象类,其中没有成员函数和成员对象,只有型别信息,它们都是把第一个引数型别的对象与第二个引数性别的对象进行某种操作

#include <iostream>
#include <vector>
#include <iterator>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <functional>
using namespace std;

class Rand
{
    public:
        int operator()()
        {
            //time函数参数为NULL时,返回值是从1970年1月1日至今所经历的时间(以秒为单位) 
            srand((unsigned)time(NULL));//随着seed的不同,产生的随机数不同 
            return rand()%(10+1);
        }
};
int main()
{
    vector<int> v{1,2,3};
    vector<int> v1(v.size());
    
    generate(v1.begin(),v1.end(),Rand());
    for_each(v1.begin(),v1.end(),[](int i)
    {
        cout<<i<<" ";
    });
    cout<<endl;
    
    //plus<T>():加法 
    transform(v.begin(),v.end(),v1.begin(),ostream_iterator<int>(cout," "),plus<int>());//创建一个匿名对象
    cout<<endl;
    //minus<T>():减法
    transform(v.begin(),v.end(),v1.begin(),ostream_iterator<int>(cout," "),minus<int>()); 
    cout<<endl;
    //multiplies<T>():乘法
    transform(v.begin(),v.end(),v1.begin(),ostream_iterator<int>(cout," "),multiplies<int>());
    cout<<endl;
    //divides<T>():除法
    transform(v.begin(),v.end(),v1.begin(),ostream_iterator<int>(cout," "),divides<int>());
    cout<<endl; 
    //modulus<T>():取余
    transform(v.begin(),v.end(),v1.begin(),ostream_iterator<int>(cout," "),modulus<int>());
    cout<<endl;
    //negate<T>():取反
    transform(v.begin(),v.end(),ostream_iterator<int>(cout," "),negate<int>());
    cout<<endl;
    return 0;
}

大小比较

  继承于binary_function<T,T,bool>,只有第一个型别的对象与第二个型别的对象相等时,才返回true

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <functional>
using namespace std;

int main()
{
    //equal_to<T>():等于,把等于0的放在前一部分,不等于0的放在后一部分 
    vector<int> v{1,2,3,0,-1,-6};
    partition(v.begin(),v.end(),bind2nd(equal_to<int>(),0));
    for_each(v.begin(),v.end(),[](const int &i)->void
    {
        cout<<i<<" ";
    });
    cout<<endl;

    //not_equal_to<T>():不等于,
    partition(v.begin(),v.end(),bind2nd(not_equal_to<int>(),0));
    for_each(v.begin(),v.end(),[](const int &i)->void
    {
        cout<<i<<" ";
    });
    cout<<endl;
    
    //less<T>():<:把小于0的放后面 
    partition(reverse_iterator<vector<int>::iterator>(v.end()),reverse_iterator<vector<int>::iterator>(v.begin()),bind2nd(less<int>(),0));
    for_each(v.begin(),v.end(),[](const int &i)->void
    {
        cout<<i<<" ";
    });
    cout<<endl;
    
    //less_equal<T>():<=把小于0的放前面 
    partition(v.begin(),v.end(),bind2nd(less_equal<int>(),0));
    for_each(v.begin(),v.end(),[](const int &i)->void
    {
        cout<<i<<" ";
    });
    cout<<endl;
    
    //greater<T>():>,把大于0的放前面 
    partition(v.begin(),v.end(),bind2nd(greater<int>(),0));
    for_each(v.begin(),v.end(),[](const int &i)->void
    {
        cout<<i<<" ";
    });
    cout<<endl;
    
    //greater_equal<T>():>=,把大于等于0的放后面 
    partition(reverse_iterator<vector<int>::iterator>(v.end()),reverse_iterator<vector<int>::iterator>(v.begin()),bind2nd(greater_equal<int>(),0));
    for_each(v.begin(),v.end(),[](const int &i)->void
    {
        cout<<i<<" ";
    });
    cout<<endl;

    return 0;
}

 逻辑运算

  f为logical_and<T>的一个object,x,y都是型别T之值,只有当f(x,y)都为true时,f(x,y)才返回true;logical_not x为false时,f(x)返回true

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <functional>
using namespace std;

int main()
{
    vector<int> v{1,2,3,0,-1,-6};
    auto it=find_if(v.begin(),v.end(),compose2(logical_and<int>(),bind2nd(greater_equal<int>(),0),
                        bind2nd(less_equal<int>(),2)));
    cout<<*it<<endl;
    return 0;
}

Member Function Apdater

  是面向对象编程与泛型编程的桥梁,能够把成员函数当做函数对象来使用

  1. 接受x*或x&型的引数,如果是后者命名为_ref后缀
  2. 是无因数或单一引数的成员函数(因为类成员函数的第一个参数已定义为this指针),后者,命名为'1'后缀
  3. 封装是non-const或const member function,后者,前冠有const_前缀

mem_fun_t<R,X>

  1. X是class,R为member function的返回值类型
  2. Constructo需要一个指针,即X*,此时operator()接受一个型别为X*类型的引数
  3. 若F是一个mem_fun_t,一member function X::f构造出来,且x是个指针,型别为X*,那么表达式F(x)等价于x->f()
  4. mem_fun为一个辅助函数,来产生mem_fun_t

mem_fun_ref_t<R,X>

  与mem_fun_t类似

  1. 若F是一个mem_fun_t,一member function X::f构造出来,且X是个型别为x的object,那么表达式F(x)等价于x.f()
  2. Constructo需要一个指针,指向x的member function,此时operator()接受一个型别为X&类型的引数
  3. mem_fun_ref为一个辅助函数

mem_fun1_t<R,X,A>

  1. X是class,R为member function的返回值类型,A为引数型别
  2. Constructo需要一个指针,指向x的member function,此时operator()需要两个引数,第一个型别为X*,第二个型别为A
  3. 若F是一个mem_fun_t,一member function X::f构造出来,且x是个指针,型别为X*,那么表达式F(x,a)等价于x->f(a)
  4. mem_fun为一个辅助函数,来产生mem_fun1_t

mem_fun1_ref_t<R,X,A>

  1. 若F是一个mem_fun_t,一member function X::f构造出来,且X是个型别为x的object,那么表达式F(x)等价于x.f()
  2. Constructo需要一个指针,指向x的member function,此时operator()需要两个引数,第一个型别为X&,第二个型别为A
  3. mem_fun_ref为一个辅助函数

const_mem_fun_t<R,X>

  封装的是const成员函数,其他与mem_fun_t相同

const_mem_fun_ref_t<R,X>

  封装的是const成员函数,其他与mem_fun_ref_t相同

cosnt_mem_fun1_t<R,X,A>

  封装的是const成员函数,其他与mem_fun1_t相同

const_mem_fun1_ref_t<R,X,A>

  封装的是const成员函数,其他与mem_fun1_ref_t相同

 

#include <iostream>
#include <vector>
#include <map>
#include <iterator>
#include <algorithm>
#include <hash_set>
#include <functional>
using namespace std;

class Base
{
    public:
        virtual void print()=0;    
};
class B1: public Base
{
    public:
        void print()
        {
            cout<<" this is B1"<<endl;    
        }    
};
class B2: public Base
{
    public:
        void print()
        {
            cout<<" this is B2"<<endl;    
        }    
};
class Op
{
    public:
        virtual double eval(double)=0;
};
class square:public Op
{
    public:
        double eval(double x)
        {
            return x*x;    
        }    
};
class Negate:public Op
{
    public:
        double eval(double x)
        {
            return -x;    
        }    
};
int main()
{
    //mem_fun_t
    vector<Base *> v{new B1,new B2,new B1,new B2,new B2};
    for_each(v.begin(),v.end(),mem_fun(&Base::print));
    cout<<"*********************************"<<endl;
    
    //mem_fun_ref_t
    vector<B1> v1{B1(),B1()};
    for_each(v1.begin(),v1.end(),mem_fun_ref(&Base::print));
    cout<<"*********************************"<<endl;
    
    //mem_fun1_t
    vector<Op*> o{new square,new square,new Negate,new Negate,new square};
    vector<double> n{1,2,3,4,5,6};
    transform(o.begin(),o.end(),n.begin(),ostream_iterator<double>(cout," "),mem_fun(&Op::eval));
    cout<<endl<<"*********************************"<<endl;
    
    //mem_fun1_ref_t
    vector<int> v1{1,1,1,1,1};
    vector<int> v2{2,2,2,2,2};
    vector<int> v3{3,3,3,3,3};
    
    vector<vector<int> > v;
    v.push_back(v1);
    v.push_back(v2);
    v.push_back(v3);
    
    vector<int> v4{1,2,3};
    int &(vector<int>::*extract)(vector<int>::size_type);//
    extract=&vector<int>::operator[];//
    transform(v.begin(),v.end(),v4.begin(),ostream_iterator<int>(cout," "),mem_fun_ref(extract));//
    return 0; 
}

 

转载于:https://www.cnblogs.com/tianzeng/p/8711758.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值