C++使用智能指針實(shí)現(xiàn)模板形式的單例類
本文通過(guò)實(shí)例為大家分享了C++使用智能指針實(shí)現(xiàn)模板形式的單例類的具體代碼,供大家參考,具體內(nèi)容如下
實(shí)現(xiàn)一個(gè)模板形式的單例類,對(duì)于任意類型的類經(jīng)過(guò)Singleton的處理之后,都能獲取一個(gè)單例對(duì)象,并且可以傳遞任意參數(shù)
并且還使用了智能指針,把生成的單例對(duì)象托管給智能指針,從而實(shí)現(xiàn)自動(dòng)回收單例對(duì)象的資源
此外,如果需要一個(gè)放在靜態(tài)成員區(qū)的對(duì)象供其他類使用,又不希望修改原有的類的代碼,這時(shí)候可以通過(guò)該模板套一層殼,形成單例對(duì)象。
頭文件
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
{
//由于構(gòu)造和析構(gòu)被設(shè)為私有,想使用單例模板創(chuàng)造對(duì)象,就應(yīng)該把其設(shè)為友元
template <typename T> friend class Singleton;
public:
//把析構(gòu)函數(shù)設(shè)為private之后,智能指針銷毀時(shí)無(wú)法調(diào)用
//所以析構(gòu)應(yīng)該設(shè)置為public,但是就算是共有的析構(gòu),由于是把單例對(duì)象的內(nèi)容托管給了智能指針
//通過(guò)智能指針顯式的調(diào)用析構(gòu)函數(shù),也是無(wú)法回收單例對(duì)象的,所以,不影響單例模式的實(shí)現(xiàn)
~Point(){
cout << "~Point()" << endl;
}
void show(){
cout << "(" << _ix << ", " << _iy << ")" << endl;
}
private:
//單例模式,要把構(gòu)造函數(shù)和析構(gòu)函數(shù)設(shè)為私有
Point(int x, int y) : _ix(x), _iy(y)
{
cout << "Point(int, int)" << endl;
}
/* ~Point(){ */
/* cout << "~Point()" << endl; */
/* } */
private:
int _ix;
int _iy;
};
class Computer
{
//由于構(gòu)造和析構(gòu)被設(shè)為私有,想使用單例模板創(chuàng)造對(duì)象,就應(yīng)該把其設(shè)為友元
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的析構(gòu)函數(shù),不影響單例模式的實(shí)現(xiàn)
~Computer(){
cout << "~Computer()" << endl;
}
private:
//單例模式,要把構(gòu)造函數(shù)設(shè)為私有
//使用模板生成單例對(duì)象的時(shí)候調(diào)用了make_shared函數(shù),如果傳入的是棧上的內(nèi)容
//make_shared函數(shù)會(huì)調(diào)用拷貝構(gòu)造函數(shù)在堆上重新生成一個(gè)托管給智能指針的對(duì)象,
//并把原先的對(duì)象銷毀,所以會(huì)在make_shared里面執(zhí)行一次析構(gòu)函數(shù)
/* Computer(const Computer &rhs){ */
/* cout << "拷貝構(gòu)造函數(shù)" << endl; */
/* } */
Computer(const string &name, const int price)
:_name(name), _price(price)
{
cout << "Computer(const string &, const int &)" << endl;
}
/* ~Computer(){ */
/* cout << "~Computer()" << endl; */
/* } */
private:
string _name;
int _price;
};
//模板形式的單例類(使用了智能指針),應(yīng)該使用飽漢模式
template <typename T>
class Singleton
{
public:
template <typename ...Args>
static shared_ptr<T> getInstance(Args... args){
if(_pInstance == nullptr){
//這里會(huì)直接調(diào)用相應(yīng)的類型的構(gòu)造函數(shù),托管給智能指針,類型在實(shí)例化后確定
/* //使用臨時(shí)對(duì)象托管給智能指針的時(shí)候,由于臨時(shí)對(duì)象分配在棧上, */
/* //所以在make_shared內(nèi)部會(huì)重新分配堆上的空間來(lái)保存其內(nèi)容, */
/* //會(huì)調(diào)用拷貝構(gòu)造函數(shù),并把臨時(shí)對(duì)象銷毀 */
/* _pInstance = make_shared<T>(T(args...)); */
//如果把一個(gè)分配在堆上的指針托管給智能指針,傳入的指針就不會(huì)被銷毀
T *tmp = new T(args...);
_pInstance = make_shared<T>(*tmp);
}
return _pInstance;
}
private:
//由于使用了模板,所以_pInstance實(shí)際上指向的是 T ,而非本類型,
//所以并不會(huì)生成Singleton對(duì)象,而是直接生成相應(yīng)的T對(duì)象
//T在實(shí)例化之后才會(huì)確定,究竟是哪種類型,
//所以Singleton的構(gòu)造函數(shù)和析構(gòu)函數(shù)并不會(huì)執(zhí)行
Singleton(){
cout << "Singleton()" << endl;
}
~Singleton(){
cout << "~Singleton()" << endl;
}
static shared_ptr<T> _pInstance; //單例模式的指針,指向唯一的實(shí)體
};
//由于類型在實(shí)例化是才會(huì)確定,所以使用飽漢模式
template <typename T>
shared_ptr<T> Singleton<T>::_pInstance = nullptr;
測(cè)試文件
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 << "通過(guò)模板,可以生成不同類型的單例對(duì)象:" << endl;
cout << "pt3: ";
pt3->show();
cout << "pt4: ";
pt4->show();
cout << endl << "使用了智能指針,不同對(duì)象指向的地址也一樣:" << 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;
}
運(yùn)行結(jié)果
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) # 通過(guò)模板,可以生成不同類型的單例對(duì)象: pt3: (1, 2) pt4: (1, 2) # 使用了智能指針,不同對(duì)象指向的地址也一樣: &pc1 = 0x7ffe83bbd390 &pc2 = 0x7ffe83bbd3a0 &pt3 = 0x7ffe83bbd3b0 &pt4 = 0x7ffe83bbd3c0 &(*pc1) = 0x55b750c7e300 &(*pc2) = 0x55b750c7e300 &(*pt3) = 0x55b750c7e360 &(*pt4) = 0x55b750c7e360 ~Point() ~Computer()
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C++實(shí)現(xiàn)LeetCode(100.判斷相同樹)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(100.判斷相同樹),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
詳解Bucket Sort桶排序算法及C++代碼實(shí)現(xiàn)示例
桶排序是一種線性排序算法,這里我們來(lái)詳解Bucket Sort桶排序算法及C++代碼實(shí)現(xiàn)示例,需要的朋友可以參考下2016-07-07
C++實(shí)現(xiàn)LeetCode(120.三角形)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(120.三角形),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
C++實(shí)現(xiàn)LeetCode(151.翻轉(zhuǎn)字符串中的單詞)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(151.翻轉(zhuǎn)字符串中的單詞),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
C++實(shí)現(xiàn)簡(jiǎn)單版圖書管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)單版圖書管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06

