for_each调用类成员函数,mem_fun, mem_fun_ref用法

先看一个STL中for_each的用法

[cpp]  view plain copy
  1. #include <iostream>  
  2. #include <vector>  
  3. #include <algorithm>  
  4. #include <functional>  
  5. #include <iterator>  
  6. using namespace std;  
  7. class Test  
  8. {  
  9. public:  
  10.     Test(int _data = 0):data(_data){}  
  11.       
  12.     void print(){cout<<"i am class Test"<< data<<endl;}  
  13.     void add(int b){ data += b;}  
  14.     int data;  
  15. };  
  16.   
  17. int val[] = {0,1,2,3,4,5,6};  
  18. int main()  
  19. {   Test t(3);  
  20.     vector<int> ivec(val,val+7);  
  21.     vector<Test> tvec;  
  22.     copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(tvec));  
  23.     /*这个地方是将int隐式转化为Test类型了,与本主题无关,使用ctrl+z结束输入*/  
  24.     for_each(tvec.begin(),tvec.end(),Test::print);  
  25.     for_each(ivec.begin(),ivec.end(),t.add);  
  26. }  


我们的目的很明显,

1.输出vector<Test>的所有变量 ,, 通过调用成员变量print函数

2.将ivec中的七个数加上类变量t中,使用t.add(int)函数.

但是上面的1,2两句确怎么也无法成功...   (当然了可以用for循环来做,,但这就违背了Template的初忠了)

下面讲解下方法:

1.对于

[cpp]  view plain copy
  1. for_each(tvec.begin(),tvec.end(),&Test::print);  
这里要引出mem_fun或者mem_fun_ref这个函数适配器了. 正确的写法:

[cpp]  view plain copy
  1. for_each(tvec.begin(),tvec.end(),mem_fun_ref(&Test::print));  
这样就能成功达到我们的第一个目的了.

分析下mem_fun_ref这个东西 可以看下源码

[cpp]  view plain copy
  1.     // TEMPLATE FUNCTION mem_fun_ref  
  2. emplate<class _Result,  
  3. class _Ty> inline  
  4. mem_fun_ref_t<_Result, _Ty> mem_fun_ref(_Result (_Ty::*_Pm)())  
  5. {   // return a mem_fun_ref_t functor adapter  
  6. return (std::mem_fun_ref_t<_Result, _Ty>(_Pm));  
  7. }  


mem_fun_ref准确的说是个函数,他返回的是mem_fun_ref_t类. 

函数的声明为:

[cpp]  view plain copy
  1. template<class _Result, class _Ty>  
  2. inline mem_fun_ref_t<_Result,_Ty> mem_fun_ref(_Result (_Ty::*_Pm)());  
mem_fun_ref函数的形参是一个类成员函数指针为   _Result (_Ty::*_Pm)()    ,  注意最右边的空() ,  这个函数指针无参数,,  类为_Ty ,  类成员函数指针为_Pm,  成员函数返回值为_Result

故拿这个来说明下:

[cpp]  view plain copy
  1. mem_fun_ref(&Test::print)  

这句将返回一个mem_fun_ref_t的类 , 其中:

_Result  为Test::print的返回值  , ,, 即  void

_Ty 为Test::print的类    ,, ,, , ,, 即    Test

_Pm为类成员函数指针 , 即  &print

然后再看下class mem_fun_ref_t的定义

[cpp]  view plain copy
  1.         // TEMPLATE CLASS mem_fun_ref_t  
  2. template<class _Result,  
  3.     class _Ty>  
  4.     class mem_fun_ref_t  
  5.         : public unary_function<_Ty, _Result>  
  6.     {   // functor adapter (*left.*pfunc)(), non-const *pfunc  
  7. public:  
  8.     explicit mem_fun_ref_t(_Result (_Ty::*_Pm)())  
  9.         : _Pmemfun(_Pm)  
  10.         {   // construct from pointer  
  11.         }  
  12.   
  13.     _Result operator()(_Ty& _Left) const//重要的是这一句,,注意了!  
  14.         {   // call function  
  15.         return ((_Left.*_Pmemfun)());  
  16.         }  
  17.   
  18. private:  
  19.     _Result (_Ty::*_Pmemfun)(); // the member function pointer  
  20.     };  


模板类mem_fun_ref_t中前面已经分析了对于
[cpp]  view plain copy
  1. mem_fun_ref(&Test::print)  
来说_Result  = void  , _Ty = Test .   构造函数将_Pmemfun指针指向 &Test::print成员函数

该类重载了operator() 故为仿函数(functor) ,
对于最前面的for_each ,  第三个实参为函数指针_pfn , , 

for_each内部会这样调用 _pfn( Test)

那么应用到这里,即

_Result operator()(_Ty &_Left)const

{return ((_Left.*_Pmemfun)());} 

每次传给这个仿函数一个functor, ,然后成为变量_Left , 调用 _Left.print  就达到了目的( 对tvec里面的每一个Test类变量 ,  都调用自身的print成员函数.


ps: 至于mem_fun这个的用法,差不多 

当对于vector<Test*> ptvec;时 , 就得用mem_fun ,,,可以自已分析下源码


2.mem_fun1_ref,

上述例子中的第二个for_each解决方案, 就得使用me_fun1_ref 这个会返回带一个参数的funtor(仿函数)  , 具体分析待续

.....



3.修改后的程序为

[cpp]  view plain copy
  1. #include <iostream>  
  2. #include <vector>  
  3. #include <algorithm>  
  4. #include <functional>  
  5. #include <iterator>  
  6. using namespace std;  
  7. class Test  
  8. {  
  9. public:  
  10.     Test(int _data = 0):data(_data){}  
  11.   
  12.     void print(){cout<<"i am class Test"<< data<<endl;}  
  13.     void add(int b){ data += b;}  
  14.     int data;  
  15. };  
  16.   
  17. int val[] = {0,1,2,3,4,5,6};  
  18. int main()  
  19. {   Test t(3);  
  20.     vector<int> ivec(val,val+7);  
  21.     vector<Test> tvec;  
  22.     copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(tvec));//这个地方是将int隐式转化为Test类型了,与本主题无关  
  23.     for_each(tvec.begin(),tvec.end(),mem_fun_ref(&Test::print));  
  24.     for_each(ivec.begin(),ivec.end(),bind1st(mem_fun1_ref(&Test::add),t)); //此句在vs2008上通不过,,别的IDE,codeblock上面没mem_fun1_ref这个东西,,看vs2010行不行了  
  25. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值