打印

再谈C++单例模式

[复制链接]
930|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
keer_zu|  楼主 | 2014-12-26 09:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
        单例模式是应用最多的一种设计模式,它要求每个类有且只能有一个实例对象,所以用C++设计一个单例模式的方法如下:

        1 构造函数声明为私有;   这样就保证了不能随意构造一个对象

        2 将拷贝构造函数与等号运算符声明为私有,并不提供他们的实现; 即禁止对象被拷贝。

        3 在类中声明一个静态的全局访问接口;

        4 声明一个静态的私有实例化指针;

        
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片

    class Singleton  
    {  
    public:  
        //全局访问接口  
        static Singleton *GetInstance()  
        {  
            if( instance_ == NULL )  
            {  
                instance_ = new Singleton;  
            }  
            return instance_;  
        }  
      
        ~Singleton()  
        {  
            cout << "~Singleton"<< endl;  
        }  
      
    private:  
        Singleton(const Singleton& other);  
        Singleton & operator=(const Singleton & other);  
        Singleton()  
        {  
              cout << "Singleton"<<endl;  
        }  
      
      
        static Singleton *instance_; //引用性声明  
    };  
      
    Singleton * Singleton::instance_; //定义性声明  
      
    int main(void)  
    {  
        Singleton *s1 = Singleton::GetInstance();  
        Singleton *s2 = Singleton::GetInstance();  //s2的地址等于s1,即指向同一对象  
      
        //Singleton s3(*s1); //既然是单例模式,是不允许被拷贝的。编译会出错  
      
        return 0;  
    }  

        上面就是单例类模式的C++实现,但是上述代码还有一个缺陷:单例类中申请的一些资源没有被释放,如instance_指向的空间没有被回收。一共有两种解决方式:

相关帖子

沙发
keer_zu|  楼主 | 2014-12-26 09:17 | 只看该作者
        第一种解决方式:

        
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片

    class Singleton  
    {  
        ...  
        //提供一个回收接口,在应用中显示调用回收资源  
        static void Free()  
        {  
            delete instance_;  
        }  
      
        ....  
    };  
      
    int main()  
    {  
        ...  
        Singleton::Free(); //要显示调用进行资源回收  
    }  

        这种方式虽然能实现功能,但是不太方便,每次都要手动回收资源,这是它的缺点。

  

使用特权

评论回复
板凳
keer_zu|  楼主 | 2014-12-26 09:18 | 只看该作者
      第二种解决方式:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片

    class Singleton  
    {  
        ...  
    public:  
        class Garbo //资源回收机制  
        {  
        public:  
            ~Garbo()  
            {  
                if( Singleton::instance_ != NULL )  
                {  
                    delete instance_;  
                }  
            }  
        };  
      
        ...  
    private:  
        ...  
        static Garbo garbo_;  //引用性声明  
    };  
      
    Singleton::Garbo Singleton::garbo_;//定义性声明  

        这种方式提供的处理方式显然要比第一种方式来的要便捷,因为它依靠内部提供的Garbo嵌套类来提供服务,当Singleton类生命周期结束时,Garbo的类对象garbo_也要销毁,它将调用析构函数,而在析构函数中又自动地释放了Singleton单例类申请的一些资源,这种实现就比较智能化。不需要手动释放资源。这是它的优势。

        

使用特权

评论回复
地板
keer_zu|  楼主 | 2014-12-26 09:18 | 只看该作者

        下面提供另一种实现C++单例类模式的方法:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片

    class Singleton  
    {  
     public:  
        static Singleton& GetInstance()  
        {  
            static Singleton instance_;                   return instance_;  
        }  
      
        ~Singleton()  
        {  
            cout << "~Singleton"<<endl;  
        }  
    private:  
      
        Singleton()  
        {  
            cout << "Singleton "<<endl;  
        }  
        Singleton(const Singleton &other);  
        Singleton & operator=(const Singleton &other);  
    };  

        这种实现方式利用了static修改函数内部的变量,当第一次调用GetInstance函数时,系统将构造一个Singleton对象,在后续再次调用这个函数时,系统不再执行这个语句,也就不会再构造Singleton类对象了,而直接返回instance_本身。另外,当Singleton类对象生命周期结束时,对象会自动调用析构函数销毁,这里也就不存在申请资源之类的了,需要注意的是GetInstance()函数返回的是引用,这样就不会调用拷贝构造函数了,使用时也应该声明Singleton的引用,如下:

      
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片

    int main()  
    {  
        Singleton &s1 = Singleton::GetInstance();  
        Singleton &s2 = Singleton::GetInstance(); //s1与s2是同一对象的引用  
      
        return 0;  
    }  

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:qq群:49734243 Email:zukeqiang@gmail.com

1349

主题

12426

帖子

53

粉丝