雖然經常提到閉包,但我對閉包概念不清晰。隱約感覺如果函式 A 中定義並回傳函式 B,而函式 B 在函式 A 之外仍能正常執行並存取函式 A 中定義的變數,同時函式 A 的變數不被外部存取,就叫閉包——若理解錯誤請當我沒說。
看到有人用 C++11 的 std::bind 實作閉包,其實用 C++03 的兩個特性就能實作:區域類別和靜態區域變數。
C++ 允許在函式內部定義靜態區域變數,離開函式時不會被銷毀:
- void func() {
- static int i = 0;
- cout << i++ << endl;
- }
多次呼叫 func 會發現輸出值持續遞增。
想在函式裡定義區域函式是不可能的,但可以定義區域類別,只能在該函式內使用:
- void func() {
- class LocalClass {
- private:
- // 定義私有成員
- public:
- void run() { /* ... */ }
- } obj;
- obj.run();
- }
若需將區域類別物件回傳到外部,需定義介面接收回傳物件並呼叫其方法;函式內需用 new 產生物件並回傳指標:
- class ILocal {
- public:
- virtual void run() = 0;
- };
- ILocal* func() {
- class LocalClass : public ILocal {
- public:
- virtual void run() { /* ... */ }
- };
- return new LocalClass();
- }
- #include
- using namespace std;
- // 介面法實作
- class ITest {
- public:
- void operator()() { process(); }
- protected:
- virtual void process() = 0;
- };
- ITest* test() {
- static int count = 0;
- class Test : public ITest {
- public:
- virtual void process() { cout << "Count is " << count++ << endl; }
- };
- return new Test();
- }
- // 函式指標法實作
- typedef void (*Func)(const char*);
- Func testFunc() {
- static int count = 100;
- static const char* const NAME = "James";
- class Test {
- public:
- static void process(const char* pName = NULL) {
- if (pName == NULL) pName = NAME;
- cout << pName << " Count is " << count-- << endl;
- }
- };
- return Test::process;
- }
- int main(int argc, char* argv[]) {
- ITest* pT = test();
- Func pF = testFunc();
- for (int i = 0; i < 10; i++) {
- (*pT)();
- pF((i % 2 == 0) ? NULL : "Fancy");
- }
- }
- Count is 0
- James Count is 100
- Count is 1
- Fancy Count is 99
- Count is 2
- James Count is 98
- ...
C++ 是門非常靈活的語言,我們平時用到的僅是冰山一角。雖然工作關係四五年沒用它,但它依然是我最喜歡的語言之一。