zoukankan      html  css  js  c++  java
  • cc++复习基础要点08--c++单例模式

    单例模式有许多种实现方法,在c++中,甚至可以直接用一个全局变量做到这一点,但是这样的代码显得不优雅。使用全局对象能够保证方便地访问实例,但是不能保证只声明一个对象——也就是说除了一个全局实例外,仍然能创建相同类的本地实例。

     定义一个单例类,使用类的私有静态指针变量指向类的唯一实例,并用一个公有的静态函数获取该实例。

    定义:

    class CSingleton

    {

     public:

    staticCSingleton * GetInstance()

    {

          if(m_pInstance==NULL)

                m_pInstance = new CSingleton();

          return m_pInstance;

    }

     private:

    CSingleton(){};

    staticCSingleton *  m_pInstance;

    };

    用户访问唯一实例的函数只有GetInstance()成员函数。因为类的构造函数是私有的。GetInstance()的返回值是当这个函数第一次被调用时创建的实例。所以GetInstance()之后调用都返回同一个实例的指针。

    单例类CSingleton的特征:

    1.      CSingleton有一个指向唯一实例的静态指针m_pInstance,并且是私有的;

    2.      CSingleton有一个公有的函数,可以获得这个唯一的实例,并且在需要的时候创建实例;

    3.      CSingleton的构造函数是私有的,这样就不能从别处创建该类的实例。

    但是该种实现单例类的方法有一个问题:m_pInstance指向的空间(实例)什么时候释放?

                                        该实例的析构函数什么时候执行?

    解决办法:让这个类自己知道在合适的时候把自己释放,或者把释放自己的操作让操作系统在某个适合时候执行。

    在程序结束时,系统会自动析构所有的全局变量。事实上,系统也会析构该类的所有静态成员变量。利用这个特征,可以在单例类中定义一个内嵌类的静态成员变量,而这个内嵌类的唯一工作就是在析构函数中去释放单例类的实例。

    在CSingleton类中定义一个CGarbo类的静态成员变量:

    class  CSingleton

    {

      public:

          static CSingleton * GetInstnace()

          {

                  if(m_pInstance==NULL)

                         m_pInstance = newCSingleton();

                  return m_pInstance;

          }

      private:

           CSingleton();

           static CSingleton * m_pInstance;

           class CGarbo

           {

            public:

                ~CGarbo()

                 {

                      if(CSingleton::m_pInstance)

                            delete  CSingleton::m_pInstance;

                 }  

            };

           static CGarbo Garbo;

    };

    类CGarbo被定义为CSingleton的私有内嵌类,以防该类被在其他地方滥用。

    程序运行结束时,系统会调用CSingleton的静态成员Garbo的析构函数,该析构函数会删除单例的唯一实例。

    使用这种方法释放单例对象有以下特征:

    在单例类内部定义专有的嵌套类;

    在单例类内定义私有的专门用于释放的静态成员;

    利用程序在结束时析构全局变量的特性,选择最终的释放时机;

    使用单例的代码不需要任何操作,不必关心对象的释放。

    另一种实现单例类的方法:定义单例类的实例为GetInstance函数的局部静态变量。

    class CSingleton

    {

     public:

        static  CSingleton &GetInstance()

          {

                  static CSingleton  instance;

                  return  instance;

          }

      private:

         CSingleton(){};

    };

    使用局部静态变量,非常强大的方法,完全实现了单例的特性,而且代码量更少,也不用担心单例销毁的问题。

    但使用此种方法也会出现问题,当如下方法使用单例时问题来了,

    Singletonsingleton = Singleton :: GetInstance();

    这么做就出现了一个类拷贝的问题,这就违背了单例的特性。产生这个问题原因在于:编译器会为类生成一个默认的构造函数,来支持类的拷贝。

    解决方法:禁止类拷贝和类赋值,禁止程序员用这种方式来使用单例

    class  CSingleton

    {

      public:

           static CSingleton &GetInstance()

           {

                 static CSingleton instance;

                 return instance;

           }

      private:

          CSingleton(){};

          CSingleton(const CSingleton &){};

          CSingleton & operate=(constCSingleton &){};

    };

    关于CSingleton(const Singleton&); 和 CSingleton & operate = (const Singleton&); 函数,需要声明成私用的,并且只声明不实现。这样就可以解决上边的问题,实现单例类。

  • 相关阅读:
    Redis企业级数据备份与恢复方案
    使用canal增量同步mysql数据库信息到ElasticSearch
    SpringBoot基于数据库实现简单的分布式锁
    SpringBoot+ShardingSphere实现分库分表 + 读写分离
    SpringBoot 使用JestClient操作Elasticsearch
    Java 操作 MongoDB
    VS C#开发中WinForm中Setting.settings的作用
    Sql 触发器禁用和启用
    ROW_NUMBER over (order by **)
    Aspen 安装
  • 原文地址:https://www.cnblogs.com/pangblog/p/3347832.html
Copyright © 2011-2022 走看看