C++可继承的单例基类模板

目录

  • 一、介绍
  • 二、代码
  • 三、关键处
  • 四、使用限制
  • 五、参考资料

一、介绍

最近在写一个项目,其中用到好几个单例,类本身的设计不是很复杂,但是如果每个都写一遍单例又觉得有点冗余;所以查资料写了一个单例基类模板,只要一个类继承这个基类并且以自身作为模板参数就可以实现一个单例;关于单例本身的介绍在这里不重点介绍。

特点:

  • RAII,使用 std::shared_ptr来管理资源
  • 线程安全,加了锁
  • 以上特性基于C++11

二、代码

// bridf: a singleton base class offering an easy way to create singleton
#include <memory> // shard_ptr
#include <mutex>
#include <iostream>
template<typename T>
class Singleton{
    typedef std::shared_ptr<T> Ptr;
protected:
    Singleton() noexcept=default;
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
    virtual ~Singleton() = default;
    static Ptr instance_ptr;
    static std::mutex singleton_mutex;
public:

    static Ptr get_instance() noexcept(std::is_nothrow_constructible<T>::value)
    {
        if(instance_ptr==nullptr){
           std::lock_guard<std::mutex> lk(singleton_mutex);
           if(instance_ptr==nullptr){
                instance_ptr = std::shared_ptr<T>(new T());
           }
        }
        return instance_ptr;

    }
};
template <typename T>
std::shared_ptr<T> Singleton<T>::instance_ptr=nullptr;

template <typename T>
std::mutex Singleton<T>::singleton_mutex;

/********************************************/
// Example:
// 1.friend class declaration is requiered!
// 2.constructor should be private

class DerivedSingle:public Singleton<DerivedSingle>{
   // !!!! attention!!!
   // needs to be friend in order to
   // access the private constructor/destructor
   friend class Singleton<DerivedSingle>;
   int value;
public:

   void info(){
       std::cout<<"value: \n";
       std::cout<<value<<std::endl;
   }
   void set_value(int i){
       value  = i;
   }
   int get_value(){
       return value;
   }
private:
   DerivedSingle():value(0){}
   DerivedSingle(const DerivedSingle&)=delete;
   DerivedSingle& operator =(const DerivedSingle&)= delete;
};

int main(int argc, char* argv[]){
    std::shared_ptr<DerivedSingle> instance  = DerivedSingle::get_instance();
    instance->info();
    instance->set_value(1);
    std::shared_ptr<DerivedSingle> instance2 = DerivedSingle::get_instance();
    instance2->info();
    return 0;
}

以上代码放在了 我的github中: https://github.com/sunchaothu/AdvancedCpp/tree/master/singleton

三、关键处

  • 子类需要把自己作为模板参数,如 class DerivedSingle:public Singleton<DerivedSingle>;

    这里用到的是CRTP(Curiously recurring template pattern) 递归循环模板模式

  • 在子类中需要把基类 Singleton 声明为友元;这样才能访问私有构造函数

四、使用限制

继承了这个类的代码不可以作为基类再被继承。

五、参考资料

以上代码参考了以下链接;如果有纰漏之处,还请指正,以免误人子弟!

  1. https://stackoverflow.com/questions/34519073/inherit-singleton?r=SearchResults
  2. https://www.cnblogs.com/lidabo/p/3949226.html

原文地址:https://www.cnblogs.com/sunchaothu/p/10353507.html

时间: 2024-08-26 05:41:26

C++可继承的单例基类模板的相关文章

可以继承的C++ Singleton基类

单例模式(Singleton Pattern)是设计模式中的一种,它用来保证系统中最多只能存在一个它的实例,其做法是由类自身来创建和持有它的对象实例,把对实例的创建权和管理权都控制在自己手中,以便控制实例数目. 关于如何在C++中实现单例模式的讨论已经太多了,我只是简单介绍一下可以继承的单例类. 首先介绍一下通常所见的单例类的写法,不妨设这个类叫做Singleton. Singleton.h: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

Lua面向对象----类、继承、多继承、单例的实现

(本文转载)学习之用,侵权立删! 原文地址   http://blog.csdn.net/y_23k_bug/article/details/19965877?utm_source=tuicool&utm_medium=referral lua面向对象实现: 一个类就像是一个创建对象的模具.有些面向对象语言提供了类的概念,在这些语言中每个对象都是某个特定类的实例.lua则没有类的概念,每个对象只能自定义行为和形态.不过,要在lua中模拟类也并不困难. lua中,面向对象是用元表这个机制来实现.

Python接口测试实战4(下) - 框架完善:用例基类,用例标签,重新运行上次失败用例

如有任何学习问题,可以添加作者微信:lockingfree 课程目录 Python接口测试实战1(上)- 接口测试理论 Python接口测试实战1(下)- 接口测试工具的使用 Python接口测试实战2 - 使用Python发送请求 Python接口测试实战3(上)- Python操作数据库 Python接口测试实战3(下)- unittest测试框架 Python接口测试实战4(上) - 接口测试框架实战 Python接口测试实战4(下) - 框架完善:用例基类,用例标签,重新运行上次失败用例

【转载】 C++多继承中重写不同基类中相同原型的虚函数

本篇随笔为转载,原文地址:C++多继承中重写不同基类中相同原型的虚函数. 在C++多继承体系当中,在派生类中可以重写不同基类中的虚函数.下面就是一个例子: class CBaseA { public: virtual void TestA(); }; class CBaseB { public: virtual void TestB(); }; class CDerived : public CBaseA, public CBaseB { public: virtual void TestA()

C++ 类的继承五(多继承的二义性--虚基类)

//多继承的二义性--虚基类(了解为主) #include<iostream> using namespace std; /* 多继承在现在的项目开发中一般不使用,他会增加项目的复杂度 */ class Point{ public: Point(){ x = 1; y = 1; } int x; int y; }; class PointA :virtual public Point{ public: PointA(){ a = 2; } int a; }; class PointB :vir

模板与继承之艺术——空基类优化

1.概念 C++中有“空”类的概念,这就意味着在运行期间其内部不好任何内存. 只包含类型的成员函数.非虚成员函数和静态数据成员的类为空类. 非静态的数据成员,虚函数和虚基类则在运行时期消耗存储空间. 2.空基类优化如下: #include<iostream> using namespace std; class Empty{ typedef int Int; }; class EmptyToo : public Empty {}; class EmptyThree : public Empty

封装、继承、单例

封装 package com.qianfeng.test; //封装性:(根据对属性的封装来说明):把对成员变量的访问进行私有化,通过一个公共的方法间接的实现访问. //好处:提高了代码的安全性,增加了代码的可读性和复用性. public class Demo2 { public static void main(String[] args) { /* * 开枪射击 */ Gun gun = new Gun(); //我们把程序中出现的不符合逻辑的数据称为脏数据 /* * 原因:直接将脏数据赋值

5、继承与派生6-虚基类

当某类的部分或全部直接基类是从另一个共同基类派生而来时,在这些直接基类中从上一级共同基类继承来的成员就拥有相同的名称.在派生类的对象中,这些同名数据成员在内存中同时拥有多个拷贝,同一个函数名会有多个映射.我们可以使用作用域分辨符来惟一标识并分别访问他们,也可以将共同基类设置为虚基类,这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射.这样就解决了同名成员的惟一标识问题. 虚基类的声明是在派生类的定义过程中进行的,语法形式: class 派生类名:virtua

创建单例实体类

package xiancheng;/** * 单例创建的方式 * 1.懒汉式 * 2.饿汉式 * 3.利用内部类的方式 * @author User * */ public class lianxi18 {}/** * 加入内部类的形式 类在使用的形式才加载 延缓加载时间 * @author User * */class demo03 { private static class jvmholder{ public static demo03 instance=new demo03(); }