先看一個STL中for_each的用法
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <iterator>
using namespace std;
class Test
{
public:
Test(int _data = 0):data(_data){}
void print(){cout<<"i am class Test"<< data<<endl;}
void add(int b){ data += b;}
int data;
};
int val[] = {0,1,2,3,4,5,6};
int main()
{ Test t(3);
vector<int> ivec(val,val+7);
vector<Test> tvec;
copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(tvec));
/*這個地方是將int隱式轉化爲Test類型了,與本主題無關,使用ctrl+z結束輸入*/
for_each(tvec.begin(),tvec.end(),Test::print);
for_each(ivec.begin(),ivec.end(),t.add);
}
我們的目的很明顯,
1.輸出vector<Test>的所有變量 ,, 通過調用成員變量print函數
2.將ivec中的七個數加上類變量t中,使用t.add(int)函數.
但是上面的1,2兩句確怎麼也無法成功... (當然了可以用for循環來做,,但這就違背了Template的初忠了)
下面講解下方法:
1.對於
for_each(tvec.begin(),tvec.end(),&Test::print);
這裏要引出mem_fun或者mem_fun_ref這個函數適配器了. 正確的寫法:
for_each(tvec.begin(),tvec.end(),mem_fun_ref(&Test::print));
這樣就能成功達到我們的第一個目的了.
分析下mem_fun_ref這個東西 可以看下源碼
// 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));
}
函數的聲明爲:
template<class _Result, class _Ty>
inline mem_fun_ref_t<_Result,_Ty> mem_fun_ref(_Result (_Ty::*_Pm)());
mem_fun_ref函數的形參是一個類成員函數指針爲 _Result (_Ty::*_Pm)() , 注意最右邊的空() , 這個函數指針無參數,, 類爲_Ty , 類成員函數指針爲_Pm, 成員函數返回值爲_Result
故拿這個來說明下:
mem_fun_ref(&Test::print)
這句將返回一個mem_fun_ref_t的類 , 其中:
_Result 爲Test::print的返回值 , ,, 即 void
_Ty 爲Test::print的類 ,, ,, , ,, 即 Test
_Pm爲類成員函數指針 , 即 &print
然後再看下class 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)());
}
private:
_Result (_Ty::*_Pmemfun)(); // the member function pointer
};
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,
3.修改後的程序爲
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <iterator>
using namespace std;
class Test
{
public:
Test(int _data = 0):data(_data){}
void print(){cout<<"i am class Test"<< data<<endl;}
void add(int b){ data += b;}
int data;
};
int val[] = {0,1,2,3,4,5,6};
int main()
{ Test t(3);
vector<int> ivec(val,val+7);
vector<Test> tvec;
copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(tvec));//這個地方是將int隱式轉化爲Test類型了,與本主題無關
for_each(tvec.begin(),tvec.end(),mem_fun_ref(&Test::print));
for_each(ivec.begin(),ivec.end(),bind1st(mem_fun1_ref(&Test::add),t)); //此句在vs2008上通不過,,別的IDE,codeblock上面沒mem_fun1_ref這個東西,,看vs2010行不行了
}