文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C++使用智能指针实现模板形式的单例类

2024-04-02 19:55

关注

本文通过实例为大家分享了C++使用智能指针实现模板形式的单例类的具体代码,供大家参考,具体内容如下

实现一个模板形式的单例类,对于任意类型的类经过Singleton的处理之后,都能获取一个单例对象,并且可以传递任意参数

并且还使用了智能指针,把生成的单例对象托管给智能指针,从而实现自动回收单例对象的资源

此外,如果需要一个放在静态成员区的对象供其他类使用,又不希望修改原有的类的代码,这时候可以通过该模板套一层壳,形成单例对象。

头文件

template_singleton.hpp


#include <iostream>
#include <string>
#include <memory>

using std::cout;
using std::endl;
using std::string;
using std::shared_ptr;
using std::make_shared;

template <typename T> class Singleton;

class Point
{
    //由于构造和析构被设为私有,想使用单例模板创造对象,就应该把其设为友元
    template <typename T> friend class Singleton;
    
public:
    //把析构函数设为private之后,智能指针销毁时无法调用
    //所以析构应该设置为public,但是就算是共有的析构,由于是把单例对象的内容托管给了智能指针
    //通过智能指针显式的调用析构函数,也是无法回收单例对象的,所以,不影响单例模式的实现
    ~Point(){
        cout << "~Point()" << endl;
    }

    void show(){
        cout << "(" << _ix << ", " << _iy << ")" << endl;
    }

private:
    //单例模式,要把构造函数和析构函数设为私有
    Point(int x, int y) : _ix(x), _iy(y)
    {
        cout << "Point(int, int)" << endl;
    }
    
    
    

private:
    int _ix;
    int _iy;
};

class Computer
{
    //由于构造和析构被设为私有,想使用单例模板创造对象,就应该把其设为友元
    template <typename T> friend class Singleton;

public:
    void show(){
        cout << "name: " << _name << "  price: " << _price << endl;
    }
    void reset(const string &newname, const int &newprice){
        _name = newname;
        _price = newprice;
    }
    
    //使用public的析构函数,不影响单例模式的实现
    ~Computer(){
        cout << "~Computer()" << endl;
    }

private:
    //单例模式,要把构造函数设为私有
    //使用模板生成单例对象的时候调用了make_shared函数,如果传入的是栈上的内容
    //make_shared函数会调用拷贝构造函数在堆上重新生成一个托管给智能指针的对象,
    //并把原先的对象销毁,所以会在make_shared里面执行一次析构函数
    
    
    
    Computer(const string &name, const int price)
        :_name(name), _price(price) 
    {
        cout << "Computer(const string &, const int &)" << endl;
    }
    
    
    

private:
    string _name;
    int _price;
};

//模板形式的单例类(使用了智能指针),应该使用饱汉模式
template <typename T>
class Singleton
{
public:
    template <typename ...Args> 
        static shared_ptr<T> getInstance(Args... args){
            if(_pInstance == nullptr){
                //这里会直接调用相应的类型的构造函数,托管给智能指针,类型在实例化后确定
                
                
                
                

                //如果把一个分配在堆上的指针托管给智能指针,传入的指针就不会被销毁
                T *tmp = new T(args...);
                _pInstance = make_shared<T>(*tmp);
            }
            return _pInstance;
        }

private:
    //由于使用了模板,所以_pInstance实际上指向的是 T ,而非本类型,
    //所以并不会生成Singleton对象,而是直接生成相应的T对象
    //T在实例化之后才会确定,究竟是哪种类型,
    //所以Singleton的构造函数和析构函数并不会执行
    Singleton(){
        cout << "Singleton()" << endl;
    }

    ~Singleton(){
        cout << "~Singleton()" << endl;
    }

    static shared_ptr<T> _pInstance;  //单例模式的指针,指向唯一的实体
};

//由于类型在实例化是才会确定,所以使用饱汉模式
template <typename T>
shared_ptr<T> Singleton<T>::_pInstance = nullptr;

测试文件

test_template_singleton.cc


#include "template_singleton.hpp"
#include <stdio.h>

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

void test(){
    shared_ptr<Computer> pc1 = Singleton<Computer>::getInstance("Xiaomi", 6666);
    cout << "pc1: ";
    pc1->show();

    shared_ptr<Computer> pc2 = Singleton<Computer>::getInstance("Xiaomi", 6666);
    cout << "pc1: ";
    pc1->show();
    cout << "pc2: ";
    pc2->show();

    pc2->reset("Huawei", 8888);
    cout << endl << "after pc2->reset()" << endl;
    cout << "pc1: ";
    pc1->show();
    cout << "pc2: ";
    pc2->show();
    cout << endl;

    shared_ptr<Point> pt3 = Singleton<Point>::getInstance(1, 2);
    shared_ptr<Point> pt4 = Singleton<Point>::getInstance(1, 2);

    cout << endl << "通过模板,可以生成不同类型的单例对象:" << endl;
    cout << "pt3: ";
    pt3->show();
    cout << "pt4: ";
    pt4->show();

    cout << endl << "使用了智能指针,不同对象指向的地址也一样:" << endl;
    printf("&pc1 = %p\n", &pc1);
    printf("&pc2 = %p\n", &pc2);
    printf("&pt3 = %p\n", &pt3);
    printf("&pt4 = %p\n\n", &pt4);
    printf("&(*pc1) = %p\n", &(*pc1));
    printf("&(*pc2) = %p\n", &(*pc2));
    printf("&(*pt3) = %p\n", &(*pt3));
    printf("&(*pt4) = %p\n\n", &(*pt4));

}

int main()
{
    test();
    return 0;
}

运行结果


Computer(const string &, const int &)
pc1: name: Xiaomi  price: 6666
pc1: name: Xiaomi  price: 6666
pc2: name: Xiaomi  price: 6666

after pc2->reset()
pc1: name: Huawei  price: 8888
pc2: name: Huawei  price: 8888

Point(int, int)

# 通过模板,可以生成不同类型的单例对象:
pt3: (1, 2)
pt4: (1, 2)

# 使用了智能指针,不同对象指向的地址也一样:
&pc1 = 0x7ffe83bbd390
&pc2 = 0x7ffe83bbd3a0
&pt3 = 0x7ffe83bbd3b0
&pt4 = 0x7ffe83bbd3c0

&(*pc1) = 0x55b750c7e300
&(*pc2) = 0x55b750c7e300
&(*pt3) = 0x55b750c7e360
&(*pt4) = 0x55b750c7e360

~Point()
~Computer()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯