精华内容
下载资源
问答
  • c++单例模式模板
    千次阅读
    2020-02-05 14:46:57

    所有单例模类直接继承此模板即可,线程安全,效率高(无锁),延时构造。

    #include <iostream>
    using namespace std;
    
    template <typename T>
    class Singleton {
    public:
        //外部获取单例的接口
        static T& getInstance() {
            static Token token;
            static T instance(token);   //函数静态变量可以实现延时构造。
            return instance;
        }
    
        //禁止拷贝
        Singleton(const Singleton&) = delete;
        Singleton& operator=(const Singleton&) = delete;
    
    protected:
        //只有子类才能获取令牌。
        struct Token{};
    
        //构造和析构函数私有化
        Singleton() = default;
        virtual ~Singleton() = default;
    };
    
    //具体单例模式
    class Single : public Singleton<Single> {
    public:
        //Token保证,父类需要调用,其他人无法调用。
        Single(Token token) {
            cout << "construct: " << this << endl;
            //做你想做的事情。
        }
        ~Single() = default;
    
        //禁止拷贝
        Single(const Single&) = delete;
        Single& operator=(const Single&) = delete;
    
    };
    
    int main()
    {
        cout << "main begin" << endl;
        Single &s1 = Single::getInstance();
        Single &s2 = Single::getInstance();
        cout << boolalpha << (&s1 == &s2) << endl;
        cout << "main end" << endl;
        return 0;
    }
    
    更多相关内容
  • c++单例模式类模板的实现

    千次阅读 2017-08-20 18:37:49
    设计模式中的单例模式有懒汉单例模式和饿汉单例模式两种,这部分内容记录在http://blog.csdn.net/qq_29344757/article/details/75575217中。 懒汉单例模式的设计步骤为: (1) 将构造函数的访问属性设置为private,...

    设计模式中的单例模式有懒汉单例模式和饿汉单例模式两种,这部分内容记录在http://blog.csdn.net/qq_29344757/article/details/75575217中。
    懒汉单例模式的设计步骤为:
    (1) 将构造函数的访问属性设置为private,不让该类中外部生成对象
    (2) 将标志指针变量初始化为NULL
    (3) 当外部需要使用对象时,调用类的静态成员函数,该函数判断:
    若标志指针变量为NULL,则动态生成对象,并且将该对象的地址赋值给标志指针变量,最后返回该对象的地址;
    若标志指针变量不为NULL,即其值等于前面生成的对象的地址,那么直接返回该标志指针
    (正是因为这个判断操作,使得懒人单例模式是一种非线程安全的设计模式)

    饿汉单例模式的设计步骤为:
    (1) 将构造函数的访问属性设置为private,不让该类中外部生成对象
    (2) 将标志指针变量初始化为动态生成的对象的地址
    (3) 当外部需要使用对象时,调用类的静态成员函数,该函数直接返回标志指针

    不论是二者中的哪一种,我们要将设计的类赋予单例模式属性时,都需要定义静态成员指针变量p和静态成员函数instance()以获得该类唯一对象的地址,这一部分可以提取出来,作为一个单例类模板:

    1. 饿汉单例类模板

    //singleton_class.h
    #ifndef __SINGLETON_CLASS_H__
    #define __SINGLETON_CLASS_H__
    
    #include <stdio.h>
    #include <iostream>
    
    template <typename T>
    class singleton
    {
    private:
        static T* p;        //标志指针
    
    public:
        static T* instance();   //得到类型为T对象的方法
    };
    
    template <typename T>
    T* singleton<T>::p = new T();   //不管外部是否要使用对象,进入main函数前就生成T对象,p指向该对象的地址
    
    template <typename T>
    T* singleton<T>::instance()
    {
        return p;
    }
    
    #endif /* __SINGLETON_CLASS_H__ */

    2. 懒汉单例模板类

    #ifndef __SINGLETON_CLASS_H__
    #define __SINGLETON_CLASS_H__
    
    #include <stdio.h>
    #include <iostream>
    
    template <typename T>
    class singleton
    {
    private:
        static T* p;
    
    public:
        static T* instance();
    };
    
    template <typename T>
    T* singleton<T>::p = NULL;  //初始化为NULL,等到外部需要到T类型类对象时再生成对象
    
    template <typename T>
    T* singleton<T>::instance()
    {
        if (NULL == p)
            p = new T();
    
        return p;
    }
    
    #endif /* __SIGLETON_CLASS_H__ */

    上面两种方式的单例模板类测试一样:

    #include "singleton_class.h"
    
    class TestCls
    {
    private:
        TestCls(){}                             //私有化构造函数,使本类不能再外部生成对象
        TestCls(const TestCls& );               //私有化拷贝构造函数,使本类不能为其它本类对象初始化
        TestCls& operator= (const TestCls& );   //私有化赋值操作符,使本类不能为其它本类对象赋值
    
        friend class singleton<TestCls>;        //singleton模板类为本类的友缘类,它才能new对象
    
    public:
        void print_this()
        {
            printf("this = %p\n", this);
        }
    };
    
    int main(void)
    {
        TestCls* s = singleton<TestCls>::instance();
        s->print_this();
    
        TestCls* s1 = singleton<TestCls>::instance();
        s1->print_this();
    
        return 0;
    }

    编译运行:
    这里写图片描述

    展开全文
  • 也就是说,显示器、扫描枪、收款箱这三部分都应该有各自的,并且每个只能唯一地实例化一个对象,基于这种模式的程序设计,称为单例模式。  !!!单例模式只能创建一个对象,且该对象的生命周期伴随系统的整个...
  • 项目中多次使用单例模式后发现每次都是重复的构建单例,于是做了一个单例模式模板。 //单例模板 //delete 与 default 来自于 c++ 11 template <typename T> class Singleton { //使用默认构造和析构函数 ...

    单例模式几乎是最常用的设计模式,简单易懂,使用起来效果显著,在此也不对单例模式做剖析,不了解的可以自行查阅资料。
    项目中多次使用单例模式后发现每次都是重复的构建单例类,于是做了一个单例模式的模板。

    //单例模板
    //delete 与 default 来自于 c++ 11
    template <typename T>
    class Singleton {
        //使用默认构造和析构函数
        Singleton() = default;
        ~Singleton() = default;
    public:
    	//删除默认的移动、拷贝、赋值、取址
        Singleton(T &&) = delete;
        Singleton(const T &) = delete;
        void operator = (const T &) = delete;
        T *operator &() = delete;
    	//获取实例,对此处有异议也可自行查阅资料
        static T* instance()
        {
            static T object;
            return &object;
        }
    };
    

    使用示例:

    //测试类
    class Test
    {
        int id;
    public:
        void setId(int id)
        {
            this->id = id;
        }
        int getId() const
        {
            return this->id;
        }
    };
    
    int main()
    {
        Singleton<Test>::instance()->setId(5);
        std::cout << Singleton<Test>::instance()->getId() << std::endl;
    }
    

    如果使用的时候觉得调用太长,可以将其 #define 一下,如:

    #define SingletonTest Singleton<Test>::instance()
    

    使用时短小很多,减少自己手指的损耗,如下:

    int main()
    {
        SingletonTest->setId(5);
        std::cout << SingletonTest->getId() << std::endl;
    }
    

    宏定义本身是c/c++程序设计中不推荐的做法,关于宏定义是预处理期展开在此也不做赘述,个中利害还需自己斟酌。

    到这里你可能会提出质疑,我们在此处并没有做到禁止创建 Test 用户类的对象,如果你有这样的需求,那请往下看.

    为了禁止擅自创建 Test(用户类对象),我们改变下策略:

    放开模板限制
    在此不再删除取址操作(会影响返回对象的引用),取消模板类构造函数的私有化,作为基类,析构函数标记为virtual;

    template <typename T>
    class Singleton {
    public:
        Singleton() = default;
        virtual ~Singleton() = default;
        Singleton(T &&) = delete;
        Singleton(const T &) = delete;
        void operator = (const T &) = delete;
    
        static T* instance()
        {
            static T object;
            return &object;
        }
    };
    

    用户类继承单例模板
    与之前不同的是,将创建对象的限制放在了用户类(即将构造函数设置为私有),构造函数私有化后,单例模板也无法创建对象,于是,将单例模板作为友元类;

    class Test : public Singleton<Test>
    {
        int id;
        Test() = default;
    public:
        //单例模板作为友元类
        friend class Singleton;
        void setId(int id)
        {
            this->id = id;
        }
        int getId() const
        {
            return this->id;
        }
    };
    

    示例:

    int main()
    {
        //Test t;  //错误,禁止创建对象
        Test::instance()->setId(5);
        std::cout << Test::instance()->getId();
    }
    

    目前想到的方法就是这样,如有更好的的方法,还请留下宝贵的意见。

    展开全文
  • C++单例类模板详解

    2020-08-26 04:56:09
    主要介绍了C++单例类模板,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • C++单例模式以及C++单例类模板 在单例里,又分为了懒汉式和饿汉式,它们的区别在于创建实例的时间不同: 懒汉式 : 指代码运行后,实例并不存在,只有当需要时,才去创建实例(适用于单线程) 饿汉式 : 指代码一运行,实例...

    C++单例模式以及C++单例类模板

    在单例类里,又分为了懒汉式和饿汉式,它们的区别在于创建实例的时间不同:

    懒汉式 : 指代码运行后,实例并不存在,只有当需要时,才去创建实例(适用于单线程)
    饿汉式 : 指代码一运行,实例已经存在,当时需要时,直接去调用即可(适用于多线程)

    用法

    将构造函数的访问属性设置为private,
    提供一个GetInstance()静态成员函数,只能供用户访问唯一一个实例.
    定义一个静态成员指针,用来供用户获取
    重载 (=)赋值操作符以及拷贝构造函数,并设为private, 避免对象间拷贝,复制.
    简单单例类-懒汉式:

    class CSingleton
    {
    private:
        static CSingleton* m_pInstance;
     
        CSingleton()     //构造函数为private
        {
        } 
     
        CSingleton& operator = (const CSingleton& t);
        CSingleton(const CSingleton &);
    public:
        static CSingleton* getInstance()
        {
           if(m_pInstance==NULL)
               m_pInstance= new CSingleton(); 
           
            return m_pInstance;
        }
     
        void print()
        {
          cout<<this<<endl;   
        }
    };
     
    CSingleton* CSingleton::m_pInstance = NULL;
     
    int main()
    {
        CSingleton *p1=CSingleton::getInstance();
        CSingleton *p2=CSingleton::getInstance(); 
        CSingleton *p3=CSingleton::getInstance();
     
        p1->print();
        p2->print();
        p3->print();
     
        return 0;
    }
    

    打印结果

    0x6e2d18
    0x6e2d18
    0x6e2d18
    

    从打印结果可以看出,该指针对象指向的都是同一个地址,实现了一个类最多只能有一个实例(instance)存在.

    **注意:**由于实例(instance),在系统生命期中,都是存在的,所以只要系统还在运行,就不需要delete

    上面的懒汉式如果在多线程情况下 ,多个Csingleton指针对象同时调用getInstance()成员函数时,由于m_pInstance = NULL,就会创建多个实例出来.

    所以,在多线程情况下,需要使用饿汉实现

    class CSingleton
    {
    private:
     
        static CSingleton* m_pInstance;
     
        CSingleton()     //构造函数为private
        {
        }       
     
        CSingleton& operator = (const CSingleton& t);
        CSingleton(const CSingleton &); 
     
    public:
        static CSingleton* getInstance()
        { 
            return m_pInstance;
        }
    };
     
    CSingleton* CSingleton::m_pInstance = new CSingleton;
    

    单例类模板

    单例类模板,使用时候可以友元使用,可以继承使用。

    注意

    优先使用组合而非继承

    /************************************************************************/
    /* 名称:单例模板类                                                
    /* 说明:可把任何类包装成线程安全的全局单例类,	利用了C++11的智能指针和自解锁等	并实现自动GC。	*/
    /************************************************************************/
    
    #include <mutex>
    #include <memory>
    
    template<typename T>
    class CSingleton {
    public:
    
    	//获取全局单例对象
    	template<typename ...Args>
    	static std::shared_ptr<T> GetInstance(Args&&... args) {
    		if (!m_pSington) {
    			std::lock_guard<std::mutex> gLock(m_Mutex);
    			if (nullptr == m_pSington) {
    				m_pSington = std::make_shared<T>(std::forward<Args>(args)...);
    			}
    		}
    		return m_pSington;
    	}
    
    	//主动析构单例对象(一般不需要主动析构,除非特殊需求)
    	static void DesInstance() {
    		if (m_pSington) {
    			m_pSington.reset();
    			m_pSington = nullptr;
    		}
    	}
    
    private:
    	explicit CSingleton ();
    	CSingleton (const CSingleton &) = delete;
    	CSingleton & operator=(const CSingleton &) = delete;
    	~CSingleton ();
    
    private:
    	static std::shared_ptr<T> m_pSington;
    	static std::mutex m_Mutex;
    };
    
    template<typename T>
    std::shared_ptr<T> CSingleton<T>::m_pSington = nullptr;
    
    template<typename T>
    std::mutex CSingleton<T>::m_Mutex;
    
    #endif
    

    使用

    using namespace std;
    
    class Test{
    public:
    	Test(const string& strData) : m_strData(strData) {
    		cout << m_strData.data() << endl;
    	};
    	~Test() {
    		cout << "destory" << endl;
    	};
    
    private:
    	string m_strData;
    };
    
    auto main()->int { //等同于入口函数int main()
    	auto pTest = CSingleton <Test>::GetInstance("create");
    
    	CSingleton <Test>::DesInstance();
    
    	return 1;
    }
    
    #pragma once
    
    #include <QtCore/QCoreApplication>
    #include <QtCore/QAtomicPointer>
    #include <QtCore/QReadWriteLock>
    #include <QtCore/QMutex>
    #include <QtCore/QDebug>
    
    template<class T>
    class JSingleton
    {
    public:
        static T& getInstance(void); //获取唯一实例
    
    private:
        JSingleton();                                       //禁止外部构造函数
        JSingleton(const JSingleton<T> &);                  //禁止外部拷贝构造函数
        JSingleton<T>& operator = (const JSingleton<T>&);   //禁止外部赋值拷贝函数
        ~JSingleton();                                      //禁止外部析构函数
    
        QReadWriteLock              m_internalMutex;        //函数使用的读写锁
        static QMutex               m_mutex;                //实例互斥锁
        static QAtomicPointer<T>    m_instance;             //实例
    };
    
    //静态成员变量初始化
    template<class T>
    QMutex JSingleton<T>::m_mutex(QMutex::Recursive);       //一个线程可以多次锁同一个互斥量
    
    template<class T>
    QAtomicPointer<T>JSingleton<T>::m_instance;             //原子指针,默认初始化为0
    
    template<typename T>
    T& JSingleton<T>::getInstance(void)
    {
    #ifdef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
        if(!QAtomicPointer<T>::isTestAndSetNative())        //运行时检测
            qDebug() << QStringLiteral("Error: don's support TestAndSetNative!!!");
    #endif
        //双重检测加锁
        /*  ! testAndSetOrders 操作保证在原子操作前和后的的内存访问
        *    不会被重新排序。
        */
        if(m_instance.testAndSetOrdered(0, 0))          //第一次检测
        {
            QMutexLocker locker(&m_mutex);              //加锁
            m_instance.testAndSetOrdered(0, new T);     //第二次检测
        }
        return *m_instance/*.load()*/;
    }
    
    //调用示例: 如对于class JTest()
    //typedef JSingleton<JTest> test; //使用JTest来实例化模板
    //test::getInstance().fxxx();
    
    
    展开全文
  • 1、单例模式(1)需求的提出:在架构设计时,某些在整个系统生命周期中最多只能有一个对象存在(Single,Instance)(2)问题:如何定义一个,使得这个最多只能创建一个对象?要控制的对象数目,必须对外隐藏构造...
  • 在实际工程中,如果一个的对象重复持有资源的成本很高,且对外接口是线程安全的,我们往往倾向于将其以单例模式管理。 此篇我们在 C++ 中实现正确的单例模式。 选型 在 C++ 中,单例模式有两种方案可选。 一是...
  • C++ 单例类模板(详解)

    2020-12-15 08:53:28
    @C+± 单例类模板(详解) 系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考...
  • C++单例类模板

    2020-10-08 15:17:08
    在架构设计时,某些在整个系统生命周期中最多只能有一个对象存在(Single Instance) 要控制的对象数目,必须对外隐藏构造函数; 思路: 1、将构造函数的访问属性设置为private 2、定义instance并初始化为NULL...
  • C++单例模式的几种实现

    千次阅读 2022-03-20 16:47:21
    本文介绍C++单例模式的集中实现方式,以及利弊 局部静态变量方式 //通过静态成员变量实现单例 //懒汉式 class Single2 { private: Single2() { } Single2(const Single2 &) = delete; Single2 &...
  • C++单例模式实现

    2022-02-27 15:36:59
    一、单例模式 1.1 基本概念 单例 Singleton 是设计模式的一种,其特点是只提供唯一一个的实例,具有全局变量的特点,在任何位置都可以通过接口获取到那个唯一实例; 保证一个仅有一个实例; 并提供一个访问它...
  • 文章目录前言一、单例模式的应用场景二、单例...一个只能创建一个对象,让自身负责保存它的唯一实例,并提供一个访问它的全局访问接口,这就是单例模式。 Singleton 单例模式 -instance 私有 -Singe
  • 谈谈 C++ 单例模式

    2021-10-25 00:57:45
    单例模式是一个很常见的设计模式,也广泛应用于程序开发。其具有如下特点:一个只有一个实例化对象全局可以使用那么有人要问,那我不就定义一个,程序只初始化一个全局的实例就好了吗?没错,这样是...
  • 1、简单的单例模式类 class singleton{ private: singleton(); ~singleton(); singleton(const singleton&); singleton& operator=(const singleton&); public: static singleton* GetIns...
  • C++单例模板类

    2019-08-16 00:35:44
    单例模式是保证一个类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。 本文提供两种方式实现单例模板类:1、使用私有静态指针变量 2、使用局部静态变量, 具体如下: 1、私有静态指针变量 ...
  • c++友元模板单例模式

    2021-06-30 19:51:08
    1、定义一个单例模板类,以便于其他类可以继承 template <typename T> struct singleton { static T& Instance(); }; template <typename T> T& singleton<T>::Instance() { static...
  • 单例模式概述单例模式(Singleton),...单例模式的目的很简单,创建一个全局唯一的对象(or变量)。简单代码实现//Simple_Singleton.hclass Singleton { public: static Singleton* GetInstance() { if (!m_pSin
  • QT_C++单例模式懒汉+饿汉,设计模板,使用QT打开pro文件编译即可,默认控制台输出。
  • C++ 单例模式详解

    千次阅读 2020-01-07 15:08:49
    文章目录C++ 单例模式详解一、单例模式:二、单例的实现思路二、懒汉模式2.0三、最推荐的懒汉模式3.0单例模板的实现:写在最后 C++ 单例模式详解 一、单例模式: 什么是单例:在面向对象编程中,我们创建对象的过程...
  • C++单例模式模板基类

    千次阅读 2015-09-04 09:35:52
    下面用C++实现一个单例模板类,那么其他的类只需继承它,便可以成为单例类。 本例中使用了 CMutex类,是考虑多线程的情况,这个类的定义请参见笔者的另一篇博客《C++简单封装互斥量》, 链接 ...
  • C++单例模式详解

    2021-01-27 22:22:23
    一种常用的设计模式,一般指在一个进程中使用单例模式只允许存在一个实例化对象, 应用场景: 管理共享资源: 常见于程序配置文件,在整个程序运行期间,使用单例模式实例化对象来统一管理配置文件,该...
  • C++单例模式

    2018-09-17 14:46:42
    单例模式就是一个只能被实例化一次 ,更准确的说是只能有一个实例化的对象的。 创建一个单例模式(初想) 一个只能有一个实例化的对象,那么这个就要禁止别人new出来,或者通过直接定义一个对象...
  • 所谓单例模式就是让某个只能产生一个对象。那么在C++语言中该如何设计呢?用static关键字可以实现单例模式,因为static保证同时只有一个对象的产生。下面是单例模式的代码的static实现方式: class single_printer...
  • 单例模式是设计模式中的一种,本文记录和总结单例模式的定义以及C++中实现单例模式的几种懒汉式方式。 参考C++ 单例模式总结与剖析 什么是单例模式 单例(Singleton)模式的特点是这个在全局只有唯一的一个实例...
  • 单例模式模板类

    2021-10-27 15:31:24
    单例模式模板类 @(C/C++学习笔记) 模板类 #if defined(__SUPPORT_TS_ANNOTATION__) || defined(__clang__) #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) #else #define THREAD_ANNOTATION_...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,314
精华内容 4,525
关键字:

c++单例模式类模板

c++ 订阅