当前位置: 首页 > article >正文

C++单例模板类,继承及使用

前言:

单例模式可以参考如下文章:

我的设计模式,单例模式的设计和实现

c++ 单例模式的模板类 - 川野散人 - 博客园

1.为什么需要单例模板类?

场景问题:

如果需要100个单例类就需要设计100个单例模式,代码重复且冗余,不利于扩展。

单例模板类可以实现单例模式的基础功能,普通类继承它之后,就拥有单例的特性。

2.单例模板类需要具备哪些特质?如何设计?

单例模板类需要具备哪些特质?

  • 单例模板类的构造函数应该是protected的?(子类要拥有创建父类的权限,但是不能是pubic,如果是public就丧失单例特性)
  • 单例模板类的析构函数应该是protected的?(子类要拥有析构父类的权限,但是不能是pubic,会重复析构)
  • 单例模板不能使用拷贝构造
  • 单例模板不能使用拷贝赋值
  • 单例模板应提供实例的public方法

设计代码如下:

template<typename T>
class Singleton
{
protected:
    Singleton(){std::cout << "Singleton()!" << std::endl;}
    ~Singleton(){std::cout << "~Singleton()!" << std::endl;}
public:
    static T& getInstance()
    {
        static std::mutex mtx;
        static std::unique_ptr<T> uniPtr;
        if (uniPtr == nullptr)
        {
            mtx.lock();
            if (uniPtr == nullptr)
            {
                uniPtr.reset(new T());
            }
            mtx.unlock();
        }
        return *uniPtr;
    }
private:
    Singleton(const Singleton& s) = delete;
    Singleton& operator = (const Singleton& s) = delete;
};

继承者应注意哪些?

  • 继承者的构造函数应设为私有
  • 继承者应设置单例模板类为友元(父类可以调用继承者私有构造函数)
class MySingleton :public Singleton<MySingleton>
{
    friend class Singleton<MySingleton>;
private:
    MySingleton() {std::cout << "MySingleton()!" << std::endl;}
public:
    //unique_ptr需要权限销毁管理的对象
    ~MySingleton() {std::cout << "~MySingleton()!" << std::endl;}
public:
    void MySingletonSay(){std::cout << "MySingletonSay : Hello World!" << std::endl;}
};

3.测试代码

int main()
{
    {
        MySingleton::getInstance().getInstance().MySingletonSay();
    }
    {
        MySingleton::getInstance().MySingletonSay();
    }
}

输出:

Singleton()!
MySingleton()!
MySingletonSay : Hello World!
MySingletonSay : Hello World!
~MySingleton()!
~Singleton()!

4.当我设置继承者析构函数为私有时,编译unique_ptr报错

class MySingleton :public Singleton<MySingleton>
{
    friend class Singleton<MySingleton>;
private:
    MySingleton() {std::cout << "MySingleton()!" << std::endl;}
    ~MySingleton() {std::cout << "~MySingleton()!" << std::endl;}
public:
    void MySingletonSay(){std::cout << "MySingletonSay : Hello World!" << std::endl;}
};

5.继承者析构函数不显式声明,编译unique_ptr不报错,但析构不完全

class MySingleton :public Singleton<MySingleton>
{
    friend class Singleton<MySingleton>;
private:
    MySingleton() {std::cout << "MySingleton()!" << std::endl;}
public:
    void MySingletonSay(){std::cout << "MySingletonSay : Hello World!" << std::endl;}
};
  • 输出
Singleton()!
MySingleton()!
MySingletonSay : Hello World!
MySingletonSay : Hello World!
~Singleton()!

6.继承者析构函数声明为public可能出现的问题举例

#include <iostream>
#include <memory>
#include <mutex>

template<typename T>
class Singleton
{
protected:
    Singleton(){std::cout << "Singleton()!" << std::endl;}
    ~Singleton(){std::cout << "~Singleton()!" << std::endl;}
public:
    static T& getInstance()
    {
        static std::mutex mtx;
        static std::unique_ptr<T> uniPtr;
        if (uniPtr == nullptr)
        {
            mtx.lock();
            if (uniPtr == nullptr)
            {
                uniPtr.reset(new T());
            }
            mtx.unlock();
        }
        return *uniPtr;
    }
private:
    Singleton(const Singleton& s) = delete;
    Singleton& operator = (const Singleton& s) = delete;
};

class MySingleton :public Singleton<MySingleton>
{
    friend class Singleton<MySingleton>;
private:
    MySingleton() {std::cout << "MySingleton()!" << std::endl;}
public:
    //unique_ptr需要权限销毁管理的对象
    ~MySingleton() {std::cout << "~MySingleton()!" << std::endl;}
public:
    void MySingletonSay(){std::cout << "MySingletonSay : Hello World!" << std::endl;}
};


int main()
{
    {
        MySingleton::getInstance().MySingletonSay();

        delete &MySingleton::getInstance();
    }
    std::cout << "end...................." << std::endl;
}

  • 输出:出现了重复析构sos
Singleton()!
MySingleton()!
MySingletonSay : Hello World!
~MySingleton()!
~Singleton()!
end....................
~MySingleton()!
~Singleton()!

7.如上的问题怎么解决呢?欢迎观众大佬们留言


http://www.kler.cn/a/558647.html

相关文章:

  • http 协议在互联网中扮演着怎样的角色?
  • Python爬虫基础重要数据类型
  • 【亲测有效】百度Ueditor富文本编辑器添加插入视频、视频不显示、和插入视频后二次编辑视频标签不显示,显示成img标签,二次保存视频被替换问题,解决方案
  • 【2024 CSDN博客之星】大学四年,我如何在CSDN实现学业与事业的“双逆袭”?
  • 綫性與非綫性泛函分析與應用_3.例題-母本
  • 探秘路由表:网络世界的导航地图
  • 网络运维学习笔记 021 HCIA-Datacom新增知识点02 SDN与NFV概述
  • 计算机毕业设计SpringBoot+Vue.jst房屋租赁系统(源码+LW文档+PPT+讲解)
  • flutter: table calendar笔记
  • Spring Boot延迟执行实现
  • Spring MVC配置与自定义的深度解析
  • 计算机三级网络技术知识汇总【6】
  • ARM TCM(itcm和dtcm)
  • 网络安全之攻防笔记--通用安全漏洞SQL注入sqlmapOraclemongodbDB2
  • 算法系列之贪心算法
  • 分布式之Raft算法
  • Spring Boot定时任务原理
  • AI助力小微企业技术开发规范化管理 | 杂谈
  • 49 set与map的模拟实现
  • Qt常用控件之数字显示控件QLCDNumber