STL中的for_each調用類成員函數,mem_fun, mem_fun_ref用法

先看一個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));
	}


mem_fun_ref準確的說是個函數,他返回的是mem_fun_ref_t類. 

函數的聲明爲:

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_t中前面已經分析了對於
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.修改後的程序爲

#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行不行了
}


發佈了53 篇原創文章 · 獲贊 12 · 訪問量 50萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章