首页 > 编程语言 >设计模式之单例模式C++实现

设计模式之单例模式C++实现

时间:2023-03-25 18:11:29浏览次数:40  
标签:pInstance Singleton 函数 对象 创建对象 C++ 单例 设计模式

初步用C++实现单例模式,暂未考虑线程安全问题

#include <stdio.h>
#include <iostream>

using std::cout;
using std::cin;
using std::endl;

// 单例模式的设计需求:一个类只能有一个对象
// 思路:创建的对象肯定是要入内存,也就是用户态的那片空间(栈、堆、读写段、只读段)
// 如果直接将类对象的创建放在类的外面,无论放在哪块区域都是行不通的
// 故需要强制不能在类外创建对象,而对象的创建都需要走构造函数
// 这样,我们可以将构造函数设置为私有的,强制用户不可以在类外创建对象
// 于是,我们需要在类的里面创建对象,而在堆上创建对象是我们程序员最可控的区域
// 故我们选择在堆上创建对象

// 使用场景:全局唯一的对象,网页库、日志记录器

class Singleton
{
public:
    // 将对象的创建放在函数里面
    // 在类的外面访问成员函数除了使用对象加点的方式或者指针的方式(而此时的目的就是创建对象,此时是没有对象的,这两种方法行不通)
    // 还可以将成员函数用static修饰,这样在类外可以通过类名加作用域限定符的形式调用(静态成员函数的特色)
    static Singleton* getInstance()
    {
        // 为保证 只能有一个对象的需求 需要一个指针来接收堆对象的指针
        // Singleton* _pInstance;// 这样每次进来_pInstance同样为空,每次还是会进入if语句,起不到效果,因此需要将其设置为全局变量
        // 但全局变量要求是能不使用就不要使用的,故将其设置为类里的一个数据成员
        if(_pInstance == nullptr)
        {
            _pInstance = new Singleton();// 在类中创建堆对象
        }
        return _pInstance;
    }

    // 同样,为了能够在类外用类名加作用域限定符的方式去释放对象,将该函数设置为静态成员函数
    static void destroy()
    {
        // 防止double free
        if(_pInstance != nullptr)
        {
            delete _pInstance;
            _pInstance = nullptr;
        }
    }
private:
    Singleton()
    {
        cout << "Singleton()" << endl;
    }
    // 同样,析构函数需要放在private区域,防止在类外使用时,出现double free的问题
    ~Singleton()
    {
        cout << "~Singleton()" << endl;
    }
private:
    // 静态成员函数只能访问静态数据成员,故需要将其用static修饰
    static Singleton* _pInstance;
    
};

// 静态数据成员必须在读写区进行初始化
Singleton* Singleton::_pInstance = nullptr;

int main()
{

    Singleton* ps1 =  Singleton::getInstance();
    Singleton* ps2 =  Singleton::getInstance();
    
    printf("ps1 = %p\n",ps1);
    printf("ps2 = %p\n",ps2);

    Singleton::destroy();
    Singleton::destroy();
    Singleton::destroy();
    Singleton::destroy();

    // delete ps1;  // 将析构函数设置为private时,这样使用会报错

    return 0;
}


标签:pInstance,Singleton,函数,对象,创建对象,C++,单例,设计模式
From: https://www.cnblogs.com/MyXjil/p/17255286.html

相关文章

  • C++ 用户自定义字面量(operator"" _)
    目录字面量自定义字面量定义容量字面量定义时间字面量参考字面量字面量是指源码中,固定的常量。比如,constchar*p="abcd";conststd::strings="efg";constintv......
  • C++ 2023年计算机学院”新生杯“ACM天梯赛周赛(一) 二进制转化的感悟
    题目描述对于长度为5位的一个01串,每一位都可能是0或1,一共有32种可能。它们的前几个是:0000000001000100001100100请按从小到大的顺序输出这32种01......
  • c++ linux 编译 静态库 ,动态库
                        一起编译:  静态路径要用全路径    静态编译       规范写法  ......
  • 前端设计模式——委托模式
    委托模式(Delegationpattern):将一个对象的某个方法委托给另一个对象来执行,它可以帮助我们将对象之间的关系更加灵活地组织起来,从而提高代码的可维护性和复用性。在委托模式......
  • linux c++编译
                gcc-v查看版本                     指定名字    多文件编译 ......
  • c++的内存补齐
    数据类型占用的字节数:char1short2int4longlong8当我们需要进行内存补齐的时候,是看最大类型然后进行补齐。structtest{shorta;shortb;c......
  • 【C++】类与对象理解和学习(中)
    六大默认成员函数前言每个类中都含有六大默认成员函数,也就是说,即使这个类是个空类,里面什么都没有写,但是编译器依然会自动生成六个默认成员函数,可以说它们六个是祖师爷钦点的......
  • java学习日记20230325-模版设计模式
    模版设计模式利用多态的动态绑定,将通用的方法设计为模版抽象类,通过子类继承重写抽象方法实现模版调用。 父类抽象类abstractpublicclassTemplate{......
  • 设计模式相关 小题
    10.当对一个对象的改变需要同时改变其它对象,但它不知道其它对象是谁,并且也不知道具体有多少对象有待改变时,我们应该使用()A、责任链(ChainofResponsibility)B、观察者(......
  • C++餐厅点餐结算系统[2023-03-25]
    C++餐厅点餐结算系统[2023-03-25]题目某餐馆根据实际需要欲开发一套《餐厅点餐结算系统》,具体要求如下:1、系统用户包括消费者、收银员、厨师、服务员、餐厅老板、系统......