??博客主頁: 主頁
??系列專欄: C++
??感謝大家點(diǎn)贊??收藏?評(píng)論??
??期待與大家一起進(jìn)步!
一、請(qǐng)?jiān)O(shè)計(jì)一個(gè)類,只能在堆上創(chuàng)建對(duì)象
實(shí)現(xiàn)方式:
- 將類的構(gòu)造函數(shù)私有,拷貝構(gòu)造聲明成私有。防止別人調(diào)用拷貝在棧上生成對(duì)象。
- 提供一個(gè)靜態(tài)的成員函數(shù),在該靜態(tài)成員函數(shù)中完成堆對(duì)象的創(chuàng)建
class HeapOnly
{
public:
static HeapOnly* CreateObj()
{
return new HeapOnly;
}
private:
HeapOnly()
{
//...
}
HeapOnly(const HeapOnly& hp) = delete;
HeapOnly& operator=(const HeapOnly& hp) = delete;
};
二、 請(qǐng)?jiān)O(shè)計(jì)一個(gè)類,只能在棧上創(chuàng)建對(duì)象
實(shí)現(xiàn)方法:
1.同上將構(gòu)造函數(shù)私有化,然后設(shè)計(jì)靜態(tài)方法創(chuàng)建對(duì)象返回即可
2.禁用堆上的創(chuàng)建方式,new=operator new+構(gòu)造函數(shù)
3.operator new 是系統(tǒng)提供的全局函數(shù),new在底層調(diào)用operator new全局函數(shù)來申請(qǐng)空間
class StackOnly
{
public:
static StackOnly CreateObj()
{
return StackOnly();
}
// 禁掉operator new可以把下面用new 調(diào)用拷貝構(gòu)造申請(qǐng)對(duì)象給禁掉
// StackOnly obj = StackOnly::CreateObj();
// StackOnly* ptr3 = new StackOnly(obj);
// new==operator new + 構(gòu)造
//delete==析構(gòu)+operator delete
void* operator new(size_t size) = delete;
void operator delete(void* p) = delete;
private:
//構(gòu)造函數(shù)私有化
//拷貝構(gòu)造函數(shù)不能私有化,因?yàn)槲覀兩厦鍯reateObj()返回,需要
//用到拷貝構(gòu)造函數(shù)
StackOnly()
:_a(0)
{}
private:
int _a;
};
三、 請(qǐng)?jiān)O(shè)計(jì)一個(gè)類,不能被繼承
1.方法一:
// 構(gòu)造函數(shù)私有化,派生類中調(diào)不到基類的構(gòu)造函數(shù)。則無法繼承
class NonInherit
{
public:
static NonInherit GetInstance()
{
return NonInherit();
}
private:
NonInherit()
{}
};
2.方法二:
//final關(guān)鍵字,final修飾類,表示該類不能被繼承。
class A final
{
// ....
};
四、請(qǐng)?jiān)O(shè)計(jì)一個(gè)類,只能創(chuàng)建一個(gè)對(duì)象(單例模式)
單例模式:
一個(gè)類只能創(chuàng)建一個(gè)對(duì)象,即單例模式,該模式可以保證系統(tǒng)中該類只有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn),該實(shí)例被所有程序模塊共享。 比如在某個(gè)服務(wù)器程序中,該服務(wù)器的配置信息存放在一個(gè)文件中,這些配置數(shù)據(jù)由一個(gè)單例對(duì)象統(tǒng)一讀取,然后服務(wù)進(jìn)程中的其他對(duì)象再通過這個(gè)單例對(duì)象獲取這些配置信息,這種方式簡(jiǎn)化了在復(fù)雜環(huán)境下的配置管理
1.餓漢模式
就是說不管你將來用不用,程序啟動(dòng)時(shí)就創(chuàng)建一個(gè)唯一的實(shí)例對(duì)象。
class Singleton
{
public:
// 2、提供獲取單例對(duì)象的接口函數(shù)
static Singleton& GetInstance()
{
return _sinst;
}
private:
// 1、構(gòu)造函數(shù)私有
//構(gòu)造函數(shù)私有也不能調(diào)用new了
Singleton()
{
// ...
}
// 3、防拷貝
Singleton(const Singleton& s) = delete;
Singleton& operator=(const Singleton& s) = delete;
static Singleton _sinst;
//雖然為靜態(tài)類型,但依然可以使用對(duì)應(yīng)類里面的構(gòu)造函數(shù)
};
Singleton Singleton::_sinst;// 在程序入口之前就完成單例對(duì)象的初始化
餓漢模式:一開始(main函數(shù)之前)就創(chuàng)建單例對(duì)象
1、如果單例對(duì)象初始化內(nèi)容很多,影響啟動(dòng)速度
2、如果兩個(gè)單例類,互相有依賴關(guān)系。
假設(shè)有A B兩個(gè)單例類,要求A先創(chuàng)建,B再創(chuàng)建,B的初始化創(chuàng)建依賴A,但在main的外面沒辦法確定哪個(gè)類先被創(chuàng)建,可能會(huì)出現(xiàn)問題
2.懶漢模式
如果單例對(duì)象構(gòu)造十分耗時(shí)或者占用很多資源,比如加載插件啊, 初始化網(wǎng)絡(luò)連接啊,讀取文件啊等等,而有可能該對(duì)象程序運(yùn)行時(shí)不會(huì)用到,那么也要在程序一開始就進(jìn)行初始化,就會(huì)導(dǎo)致程序啟動(dòng)時(shí)非常的緩慢。 所以這種情況使用懶漢模式(延遲加載)更好。
1.普通場(chǎng)景
class Singleton
{
public:
// 2、提供獲取單例對(duì)象的接口函數(shù)
static Singleton& GetInstance()
{
if (_psinst == nullptr)
{
// 第一次調(diào)用GetInstance的時(shí)候創(chuàng)建單例對(duì)象
_psinst = new Singleton;
}
return *_psinst;
}
private:
// 1、構(gòu)造函數(shù)私有
Singleton()
{
// ...
}
~Singleton()
{
}
// 3、防拷貝
Singleton(const Singleton& s) = delete;
Singleton& operator=(const Singleton& s) = delete;
static Singleton* _psinst;
};
Singleton* Singleton::_psinst = nullptr;
2.特殊場(chǎng)景
1、中途需要顯示釋放
static void DelInstance()
{
if (_psinst)
{
delete _psinst;
_psinst = nullptr;
}
//自己寫一個(gè)靜態(tài)的函數(shù),進(jìn)行釋放操作
}
2.程序結(jié)束時(shí),需要做一些特殊動(dòng)作(如持久化)
方法:
1.我們把要寫入的數(shù)據(jù)過程放到析構(gòu)函數(shù)中
2.我們可以像智能指針那樣使用,在類里面再定義一個(gè)類GC,讓GC的析構(gòu)函數(shù)專門用來管理Singleton的析構(gòu)函數(shù),然后創(chuàng)建GC的對(duì)象,因?yàn)镚C不是指針類型為普通類型,程序結(jié)束的時(shí)候會(huì)自動(dòng)調(diào)用其析構(gòu)函數(shù),這樣也就完成了Singleton的析構(gòu)函數(shù)文章來源:http://www.zghlxwxcb.cn/news/detail-736237.html
class GC
{
public:
~GC()
{
Singleton::DelInstance();
}
};
~Singleton()
{
cout << "~Singleton()" << endl;
// map數(shù)據(jù)寫到文件中
FILE* fin = fopen("map.txt", "w");
for (auto& e : _dict)
{
fputs(e.first.c_str(), fin);
fputs(":", fin);
fputs(e.second.c_str(), fin);
fputs("\n", fin);
}
}
文章來源地址http://www.zghlxwxcb.cn/news/detail-736237.html
3.源碼
class Singleton
{
public:
// 2、提供獲取單例對(duì)象的接口函數(shù)
static Singleton& GetInstance()
{
if (_psinst == nullptr)
{
// 第一次調(diào)用GetInstance的時(shí)候創(chuàng)建單例對(duì)象
_psinst = new Singleton;
}
return *_psinst;
}
// 一般單例不用釋放。
// 特殊場(chǎng)景:1、中途需要顯示釋放 2、程序結(jié)束時(shí),需要做一些特殊動(dòng)作(如持久化)
static void DelInstance()
{
if (_psinst)
{
delete _psinst;
_psinst = nullptr;
}
}
class GC
{
public:
~GC()
{
Singleton::DelInstance();
}
};
private:
// 1、構(gòu)造函數(shù)私有
Singleton()
{
// ...
}
~Singleton()
{
cout << "~Singleton()" << endl;
// map數(shù)據(jù)寫到文件中
FILE* fin = fopen("map.txt", "w");
for (auto& e : _dict)
{
fputs(e.first.c_str(), fin);
fputs(":", fin);
fputs(e.second.c_str(), fin);
fputs("\n", fin);
}
}
// 3、防拷貝
Singleton(const Singleton& s) = delete;
Singleton& operator=(const Singleton& s) = delete;
map<string, string> _dict;
// ...
static Singleton* _psinst;
static GC _gc;
};
Singleton* Singleton::_psinst = nullptr;
Singleton::GC Singleton::_gc;
class A {
public:
A() {
cout << "gouzao" << endl;
}
~A() {
cout << "析構(gòu)函數(shù)" << endl;
}
};
到了這里,關(guān)于【C++】特殊類的設(shè)計(jì)(只在堆、棧創(chuàng)建對(duì)象,單例對(duì)象)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!