C++ 11 function

來源:互聯網
上載者:User

標籤:



function是一組函數對象封裝類的模板,實現了一個泛型的回調機制。function與函數指標比較相似,優點在於它允許使用者在目標的實現上擁有更大的彈性,即目標既可以是普通函數,也可以是函數對象和類的成員函數,而且可以給函數添加狀態。

    聲明一個function時,需要給出所封裝的函數對象的返回值類型和各個參數的類型。比如,聲明一個function,它返回一個bool類型並接受一個int類型和一個float類型的參數,可以像下面這樣:


function<bool (int, float)> f;
    下面簡要介紹一下function的比較重要的幾個介面。

function();
    預設建構函式,建立一個空的函數對象。如果一個空的function被調用,將會拋出一個類型為bad_function_call的異常。
   


template <typename F> function(F g);
    這個泛型的建構函式接受一個相容的函數對象,即這樣一個函數或函數對象,它的傳回型別與被構造的function的傳回型別或者一樣,或者可以隱式轉換,並且它的參數也要與被構造的function的參數類型或者一樣,或者可以隱式轉換。注意,也可以使用另外一個function執行個體來進行構造。這樣做,並且function g為空白,則被構造的function也為空白。使用空的函數指標和空的成員函數指標也會產生空的function。如果這樣做,並且function g為空白,則被構造的function也為空白。使用空的函數指標和空的成員函數指標也會產生空的function。
 


template <typename F> function(reference_wrapper<F> g);
    這個建構函式與前一個類似,但它接受的函數對象封裝在一個reference_wrapper中,用以避免通過值來傳遞而產生函數或函數對象的一份拷貝。這同樣要求函數對象相容於function的簽名。
 


function& operator=(const function& g);
    賦值操作符儲存g中的函數或函數對象的一份拷貝;如果g為空白,被賦值的函數也將為空白。
 


template<typename F> function& operator=(F g);
    這個泛型賦值操作符接受一個相容的函數指標或函數對象。注意,也可以用另一個 function 執行個體(帶有不同但相容的簽名)來賦值。這同樣意味著,如果g是另一個function執行個體且為空白,則賦值後的函數也為空白。賦值一個空的函數指標或空的成員函數指標也會使function為空白。
 


bool empty() const;
    這個成員函數返回一個布爾值,表示該function是否含有一個函數或函數對象。如果有一個目標函數或函數對象可被調用,它返回 false 。因為一個function可以在一個布爾上下文中測試,或者與0進行比較,因此這個成員函數可能會在未來版本的庫中被取消,你應該避免使用它。
 


void clear();
    這個成員函數清除 function, 即它不再關聯到一個函數或函數對象。如果function已經是空的,這個調用沒有影響。在調用後,function肯定為空白。令一個function為空白的首選方法是賦0給它;clear 可能在未來版本的庫中被取消。
 


result_type operator()(Arg1 a1, Arg2 a2, ..., ArgN aN) const;
    叫用作業符是調用function的方法。你不能調用一個空的 function ,那樣會拋出一個bad_function_call的異常。叫用作業符的執行會調用function中的函數或函數對象,並返回它的結果。
    下面分別給出使用function來封裝普通函數,函數對象和類的成員函數的參考代碼。

    1、普通函數



1 int Add(int x, int y)
2
3 {
4             return x+y;
5 }
6 function<int (int,int)> f = Add;
7 int z = f(2, 3);


    2、函數對象



 1 class CStudent
 2 {
 3 public:
 4             void operator() (string strName, int nAge)
 5             {
 6                 cout << strName << " : " << nAge << endl;
 7             }
 8 };
 9
10 CStudent stu;
11 function<void (string, int)> f = stu;
12 f("Mike",  12);


    3、類的成員函數



 1 struct TAdd
 2 {
 3     int Add(int x,int y)
 4     {
 5         return x+y;
 6     }
 7 };
 8
 9 function<int  (TAdd *, int, int)> f = TAdd::Add;
10 TAdd tAdd;
11 f(&tAdd, 2, 3);   // 如果前面的模板參數為傳值或引用,直接傳入tAdd即可


     接下來我們來看看使用function來儲存函數對象狀態的情況。考慮下面的代碼:



 1 class CAdd
 2 {
 3 public:
 4     CAdd():m_nSum(0) { NULL; }
 5     int operator()(int i)
 6     {
 7           m_nSum += i;
 8           return m_nSum;
 9     }
10
11     int Sum() const
12     {
13         return m_nSum;
14     }
15
16 private:
17     int m_nSum;
18 };
19
20 int main()
21 {
22     CAdd add;
23     function<int (int)> f1 = add;
24     function<int (int)> f2 = add;
25     cout << f1(10) << "," << f2(10) << "," << add.Sum() << endl;
26     return 0;
27 }


     可能和大家想象的結果不一樣,上面程式的輸出是:10,10,0。我們將同一個函數對象賦值給了兩個function,然後分別調用了這兩個function,但函數對象中m_nSum的狀態並沒有被保持,問題出在哪兒呢?這是因為function的預設行為是拷貝一份傳遞給它的函數對象,於是f1和f2中儲存的都是add對象的拷貝,調用f1和f2後,add對象中的值並沒有被修改。
    C++ 11中提供了ref和cref函數,來提供對象的引用和常引用的封裝。要使function能夠正確地儲存函數對象的狀態,我們可以這樣來修改代碼:


1 CAdd add;
2 function<int(int)> f1 = ref(add);
3 function<int(int)> f2 = ref(add);
     另外,在兩個function之間賦值時,如果源function儲存的是函數對象的拷貝,則目標function儲存的也是函數對象的拷貝;如果源function儲存的是函數對象的引用,則目標function儲存的也是函數對象的引用。



轉載    http://www.cnblogs.com/hujian/archive/2012/12/07/2807605.html

如有著作權問題,請聯絡QQ   858668791

C++ 11 function

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.