程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 局部類實現C++的閉包

局部類實現C++的閉包

編輯:關於C語言

首先說明,雖然經常提到閉包,但我對閉包這個概念還真是不清晰,隱約感覺如果函數A中定義並返回了函數B,而函數B在函數A之外仍然可以正常運行並訪問函數A中定義的變量,同時函數A中定義的變量不能被外部訪問,就叫閉包——如果這個理解錯了,那就當我啥也沒說!

看到有人寫博說通過C++11的新特性std::bind來實現閉包,仔細想了一下,其實通過C++03的兩個特性就可以實現的:一個是局部類,一個是靜態局部變量。

靜態局部變量

C++允許在函數內部定義靜態的局部變量,這些變量不會在離開函數時被銷毀,就像這樣

  1. void func() { 
  2.     static int i = 0; 
  3.     cout << i++ << endl; 

如果多次調用func,會發現輸出到控制台的值一直在遞增。

局部類 

想在函數裡定義局部函數是不可能的,C++沒這個語法。但是可以在函數裡定義局部類,這個類只能在該函數裡使用,很有意思的,就像這樣

  1. void func() { 
  2.     class LocalClass { 
  3.     private: 
  4.         // 定義私有成員 
  5.     public: 
  6.         void run() { 
  7.             // ...... 
  8.         } 
  9.     } obj; 
  10.     obj.run(); 

如果需要將局部類對象返回到外面,就需要定義一個接口,用於接收返回的對象並調用其中的方法;同時,在函數內需要使用new來生成對象並返回其指針,就像這樣

  1. class ILocal { 
  2. public: 
  3.     virtual void run() = 0; 
  4. }; 
  5.  
  6. ILocal* func() { 
  7.     class LocalClass: public ILocal { 
  8.     public: 
  9.         virtual void run() { 
  10.             // ...... 
  11.         } 
  12.     }; 
  13.     return new LocalClass(); 

基礎知識具備了,下面來實現閉包,過程就不說了,看注釋吧

  1. #include <iostream> 
  2. using namespace std; 
  3.  
  4. //////// 接口法實現 //////////////////////////////////////// 
  5. // 定義一個函數對象接口……就像C#的委托 
  6. class ITest { 
  7. public: 
  8.     // 定義這個運算符主要是為了像函數一樣調用,就像這樣:obj(); 
  9.     void operator() () { 
  10.         process(); 
  11.     } 
  12.  
  13. protected: 
  14.     // 接口函數 
  15.     virtual void process() = 0; 
  16. }; 
  17.  
  18. // 下面函數返回一個ITest對象指針 
  19. ITest* test() { 
  20.     // 函數內的靜態變量,離開函數也不會銷毀,而且可以 
  21.     static int count = 0; 
  22.  
  23.     // 定義一個局部類 
  24.     class Test: public ITest { 
  25.     public: 
  26.         // 實現ITest中定義的接口函數來實現操作 
  27.         virtual void process() { 
  28.             cout << "Count is " << count++ << endl; 
  29.         } 
  30.     }; 
  31.  
  32.     // 返回一個新的對象……這裡必須得new,你懂的 
  33.     return new Test(); 
  34.  
  35. //////// 函數法實現 //////////////////////////////////////// 
  36. // 定義測試函數指針類型 
  37. typedef void (*Func)(const char*); 
  38.  
  39. // 下面函數返回一個閉包中的函數 
  40. Func testFunc() { 
  41.     // 靜態局部變量初始化為100 
  42.     static int count = 100; 
  43.     // 靜態局部常量 
  44.     static const char* const NAME = "James"; 
  45.  
  46.     // 不能直接定義函數,只好定義局部類的靜態方法,並返回其指針 
  47.     class Test { 
  48.     public: 
  49.         // 這個定義說明可以傳入參數,同理也可以有返回值 
  50.         static void process(const char* pName = NULL) { 
  51.             if (pName == NULL) { pName = NAME; } 
  52.             cout << pName << " Count is " << count-- << endl; 
  53.         } 
  54.     }; 
  55.     return Test::process; 
  56.  
  57. //////// 程序入口:主函數 ////////////////////////////////// 
  58. int main(int argc, char* argv[]) { 
  59.     ITest* pT = test(); 
  60.     Func pF = testFunc(); 
  61.  
  62.     // 多次調用得從函數裡返回出來的函數和對象,觀察結果 
  63.     for (int i = 0; i < 10; i++) { 
  64.         (*pT)(); 
  65.         pF((i % 2 == 0) ? NULL : "Fancy"); 
  66.     } 

給個運行結果

  1. Count is 0 
  2. James Count is 100 
  3. Count is 1 
  4. Fancy Count is 99 
  5. Count is 2 
  6. James Count is 98 
  7. Count is 3 
  8. Fancy Count is 97 
  9. Count is 4 
  10. James Count is 96 
  11. Count is 5 
  12. Fancy Count is 95 
  13. Count is 6 
  14. James Count is 94 
  15. Count is 7 
  16. Fancy Count is 93 
  17. Count is 8 
  18. James Count is 92 
  19. Count is 9 
  20. Fancy Count is 91 

C++是門非常靈活的語言,我們平時用到的相對於C++ Specification來說,僅僅是冰山一角。雖然因為工作關系我已經有四五年沒用它了,但它依然是我最喜歡的語言之一。

本文出自 “邊城客棧 學海無涯” 博客,請務必保留此出處http://jamesfancy.blog.51cto.com/2516291/1166900

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved