天天看点

局部类实现C++的闭包

首先说明,虽然经常提到闭包,但我对闭包这个概念还真是不清晰,隐约感觉如果函数A中定义并返回了函数B,而函数B在函数A之外仍然可以正常运行并访问函数A中定义的变量,同时函数A中定义的变量不能被外部访问,就叫闭包——如果这个理解错了,那就当我啥也没说!

看到有人写博说通过C++11的新特性std::bind来实现闭包,仔细想了一下,其实通过C++03的两个特性就可以实现的:一个是局部类,一个是静态局部变量。

静态局部变量

C++允许在函数内部定义静态的局部变量,这些变量不会在离开函数时被销毁,就像这样

void func() { 

    static int i = 0; 

    cout << i++ << endl; 

如果多次调用func,会发现输出到控制台的值一直在递增。

局部类 

想在函数里定义局部函数是不可能的,C++没这个语法。但是可以在函数里定义局部类,这个类只能在该函数里使用,很有意思的,就像这样

    class LocalClass { 

    private: 

        // 定义私有成员 

    public: 

        void run() { 

            // ...... 

        } 

    } obj; 

    obj.run(); 

如果需要将局部类对象返回到外面,就需要定义一个接口,用于接收返回的对象并调用其中的方法;同时,在函数内需要使用new来生成对象并返回其指针,就像这样

class ILocal { 

public: 

    virtual void run() = 0; 

}; 

ILocal* func() { 

    class LocalClass: public ILocal { 

        virtual void run() { 

    }; 

    return new LocalClass(); 

基础知识具备了,下面来实现闭包,过程就不说了,看注释吧

#include <iostream> 

using namespace std; 

//////// 接口法实现 //////////////////////////////////////// 

// 定义一个函数对象接口……就像C#的委托 

class ITest { 

    // 定义这个运算符主要是为了像函数一样调用,就像这样:obj(); 

    void operator() () { 

        process(); 

    } 

protected: 

    // 接口函数 

    virtual void process() = 0; 

// 下面函数返回一个ITest对象指针 

ITest* test() { 

    // 函数内的静态变量,离开函数也不会销毁,而且可以 

    static int count = 0; 

    // 定义一个局部类 

    class Test: public ITest { 

        // 实现ITest中定义的接口函数来实现操作 

        virtual void process() { 

            cout << "Count is " << count++ << endl; 

    // 返回一个新的对象……这里必须得new,你懂的 

    return new Test(); 

//////// 函数法实现 //////////////////////////////////////// 

// 定义测试函数指针类型 

typedef void (*Func)(const char*); 

// 下面函数返回一个闭包中的函数 

Func testFunc() { 

    // 静态局部变量初始化为100 

    static int count = 100; 

    // 静态局部常量 

    static const char* const NAME = "James"; 

    // 不能直接定义函数,只好定义局部类的静态方法,并返回其指针 

    class Test { 

        // 这个定义说明可以传入参数,同理也可以有返回值 

        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 

Count is 3 

Fancy Count is 97 

Count is 4 

James Count is 96 

Count is 5 

Fancy Count is 95 

Count is 6 

James Count is 94 

Count is 7 

Fancy Count is 93 

Count is 8 

James Count is 92 

Count is 9 

Fancy Count is 91 

C++是门非常灵活的语言,我们平时用到的相对于C++ Specification来说,仅仅是冰山一角。虽然因为工作关系我已经有四五年没用它了,但它依然是我最喜欢的语言之一。

本文转自边城__ 51CTO博客,原文链接:http://blog.51cto.com/jamesfancy/1166900,如需转载请自行联系原作者

继续阅读