了解使用ptr_fun、mem_fun和mem_fun_ref的原因2(Effective stl 条款41)

上次分析了使用 mem_fun mem_fun_ref 的原因,但并没有涉及到这两个函数的原理,所以这次打算把它们的源码拿出来看看。
 
这两个函数都是模板,用来转换某些类的成员函数,使得这些成员函数能够在象 for_each 这样的函数内部调用。
先来看 mem_fun 这个模板函数吧,这个函数一共有四个重载版本:分别为转换带一个参数和不带参数的 const 和非 const 的函数共四个版本,并且按照语法 #3 进行适配。
 
我们这里只分析转换 "不带参数的成员函数" 的mem_fun函数版本,其他几个版本也都差不多:
//  TEMPLATE FUNCTION mem_fun
template < class  _Result, class  _Ty >  inline
    mem_fun_t
< _Result, _Ty >  mem_fun(   _Result (_Ty:: * _Pm)()   )
{    // return a mem_fun_t functor adapter

 
    return (std::mem_fun_t<_Result, _Ty>( _Pm)  );//返回了一个mem_fun_t对象
}
 这个 mem_fun 函数返回了一个类 mem_fun_t对象, 这个类是仿函数类:  
// TEMPLATE CLASS mem_fun_t
template <class _Result,class _Ty>
class mem_fun_t:                          //unary_function继承而来
     public unary_function<_Ty *, _Result>
{   // functor adapter (*p->*pfunc)(), non-const *pfunc
 
public :
 
    // 构造函数,参数为类 _Ty 的一个没有参数的成员函数
    explicit mem_fun_t(_Result (_Ty::*_Pm)()): _Pmemfun(_Pm
{// construct from pointer
}
 
    _Result operator()(_Ty *_Pleft) const
    {   // call function
        return ((_Pleft->*_Pmemfun)());// 按照 #3 调用函数
    }
 
private :
    _Result (_Ty::*_Pmemfun)(); // 保存需要转换的成员函数指针
 };
 

mem_fun_tunary_function继承,是一个一元仿函数类,它重载了函数调用操作符,并且具有一个参数为类_Ty对象的指针,函数利用这个指针按照方式#3调用类_Ty的成员函数_pmemfun()。仿函数mem_fun_t提供了一般形式的函数调用(#1),满足for_each函数的要求:

 

list <  Widget  *>  lpw;
for_each(lpw.begin(), lpw.end(), mem_fun(
& Widget::test));
// OK,mem_fun返回 一个mem_fun_t仿函数, 这句代码可以分解成这样:
 
mem_fun_t < void ,Widget >  mf  =  mem_fun( & Widget::test);//构造函数对象mf
for_each(lpw.begin(), lpw.end(), mf);
 
// 可以想象,for_each函数将这样调用我们的仿函数对象mf:
for  (; _ChkFirst  !=  _ChkLast;  ++ _ChkFirst)
           mf(
* _ChkFirst);    // *_ChkFirst解引后为元素类型Widget *.
 
//mf重载的调用操作符接受一个widget的指针参数,根据这个指针调用类widget的成员函数test.
 
 
 
 
接下来分析一下 mem_fun_ref 这个函数,其实它与 mem_fun 函数几乎一样,也都有四个重载本,不同的是, mem_fun_ref 函数是用来生成按照语法 #2 调用成员函数的仿函数类。
 
//  TEMPLATE FUNCTION mem_fun_ref
template < class  _Result, class  _Ty >  inline
    mem_fun_ref_t
< _Result, _Ty >  mem_fun_ref( _Result (_Ty:: * _Pm)() )
{    // return a mem_fun_ref_t functor adapter

   return (std::mem_fun_ref_t<_Result, _Ty>(_Pm));
                                     //返回一个mem_fun_ref_t对象
 
}
 

可以看到, mem_fun_ref 函数返回 mem_fun_ref_t ,而 mem_fun 函数返回 mem_fun_t, 其实这两个返回的类基本相同,只有在调用操作符里面有一点区别,我们来看看。
这是其中一个 mem_fun_ref_t 类:
 
// TEMPLATE CLASS mem_fun_ref_t
template <class _Result,class _Ty>
class mem_fun_ref_t: public unary_function<_Ty, _Result>
{   // functor adapter (*left.*pfunc)(), non-const *pfunc
 
public :
    explicit mem_fun_ref_t(_Result (_Ty::*_Pm)()): _Pmemfun(_Pm)
    {   // construct from pointer
    }
 
    _Result operator()(_Ty& _Left) const
    {   // call function
       return ((_Left.*_Pmemfun)());// mem_fun_t 主要的不同
                                    //按照语法 #2 调用成员函数
    }
 
private :
    _Result (_Ty::*_Pmemfun)(); // the member function pointer
};
 
list< Widget> vw;
for_each (vw.begin(), vw.end(), mem_fun_ref(&Widget::test));
                                   //OK,mem_fun_ref mem_fun_ref_t 仿函数
 
 
现在,这两个函数模板 mem_fun mem_fun_ref 的原理已经清楚了,它们分别返回相应的仿函数版本来实现一般形式的函数调用 ( 语法 #1) ,而仿函数内部完成实际的成员函数调用 .

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值