在http://www.cplusplus.com/reference/std/functional/mem_fun_ref上可以看到mem_fun_ref的介紹和下面這個例子
(transform演算法的例子最好先熟悉一下,在這裡:http://www.cplusplus.com/reference/algorithm/transform/)
#include <iostream><br />#include <functional><br />#include <vector><br />#include <algorithm><br />#include <string><br />using namespace std;<br />int main () {<br /> vector <string*> numbers;<br /> // populate vector of pointers:<br /> numbers.push_back ( new string ("one") );<br /> numbers.push_back ( new string ("two") );<br /> numbers.push_back ( new string ("three") );<br /> numbers.push_back ( new string ("four") );<br /> numbers.push_back ( new string ("five") );<br /> vector <int> lengths ( numbers.size() );<br /> transform (numbers.begin(), numbers.end(), lengths.begin(), mem_fun(&string::length));</p><p> for (int i=0; i<5; i++) {<br /> cout << *numbers[i] << " has " << lengths[i] << " letters./n";<br /> }<br /> return 0;<br />}
(註:mem_fun的例子是非常相似的,只是vector<string>替換成vector<string*>,mem_fun_ref替換成mem_fun,下面會提到兩者的不同點,目前先關注mem_fun_ref就可以了,mem_fun幾乎是一樣的)
class C3DFrame<br />{<br />public:<br />C3DFrame(){}<br />typedef intIRenderer;<br />typedef floatO3DReal;<br />typedef vector<O3DReal> RealArray;<br />boolRenderFrame(IRenderer *pRenderer)<br />{<br />/*mem_fun1_ref_t<void, C3DFrame, const AxisBufferParam&> tempFuncObj(&C3DFrame::prepareBuffer);<br />tempFuncObj(*this, AxisBufferParam());*/<br />renderAxisHeader(pRenderer, mem_fun_ref(&C3DFrame::prepareBuffer));<br />//renderAxisHeader(pRenderer, mem_fun_ref(&C3DFrame::prepareBufferVoid));<br />return true;<br />}<br />private:<br />template<class Operation><br />boolrenderAxisHeader(IRenderer *pRenderer, Operation op)<br />{<br />op(*this, 1);<br />//op(*this);<br />return true;<br />}<br />void prepareBuffer(int data)<br />{<br />cout << data << endl;<br />}<br />void prepareBufferVoid()<br />{<br />}<br />};
這裡是我自己編寫的一個使用mem_fun_ref的版本。
我們很容易錯誤地認為成員函數模板renderAxisHeader()中的op(*this,1)是op(1),認為調用的是prepareBuffer(1),但mem_fun_ref()產生的functor(即這裡是mem_fun1_ref_t)的operator()調用是operator(*this,parameter),所以如果這裡直接將op(*this, 1)寫成op(1)就肯定會出現錯誤了,因為mem_fun1_ref_t的operator()認為有兩個參數傳進來的,但事實上就只有一個,這是錯誤的 !!
但為什麼cplusplus中的transform演算法調用確實對的呢?
看一下transform中的虛擬碼大概是這樣的:
template < class InputIterator, class OutputIterator, class UnaryOperator ><br /> OutputIterator transform ( InputIterator first1, InputIterator last1,<br /> OutputIterator result, UnaryOperator op )<br />{<br /> while (first1 != last1)<br /> *result++ = op(*first1++); // or: *result++=binary_op(*first1++,*first2++);<br /> return result;<br />}
例子中的op是我們傳進去的functor(即mem_fun_ref_t,這是沒有參數的時候的樣子,如果有一個參數的話,會傳入mem_fun1_ref_t),但transform上的例子是傳入mem_fun_ref(&(string::length)),而length是一個沒有參數的成員函數,而transform內部是會將一個string對象出給functor的,這就說明了,為什麼transform演算法可以使用mem_fun_ref(&(string::length))這樣構造出一個functor傳遞進去了,因為上面的op(*first1++)會將一個string對象傳遞給functor,使funcor內部可以這樣調用成員函數:
(obj.*_func)()
註:obj即*first1,_func即&(string::length),()表示沒有參數
這樣調用就正確了
而mem_fun1_ref_t產生的functor的調用就如
operator(*this, 1),內部調用就如:
(obj.*_func)(1)
這樣就成功調用了指定的執行個體的成員函數了!!!!
故以後在使用mem_fun_ref和mem_fun都要主意,其第一個參數是該對象!!!而不是你傳入的參數或者沒有參數,就好像我們調用一個普通類的成員函數一樣,編譯器同樣是會將一個this指標傳給成員函數的參數列表的!!!