設計類、單例模式
阿新 • • 發佈:2018-12-20
1.請設計一個類,該類只能在堆上建立物件
方法:將類的建構函式和拷貝建構函式宣告為私有,防止別人呼叫拷貝在棧上生成物件
提供一個靜態的成員函式,在該靜態成員函式中完成堆物件的建立
class heaponly { public: static heaponly*getheap() { return new heaponly; } private: heaponly() //構造私有 {} heaponly(const heaponly&); //拷貝構造私有 }; int main() { heaponly* p1 = heaponly::getheap(); //heaponly p2; //heaponly p3(*p1); return 0; }
2.設計一個類,該類只能在棧上建立物件
class stackonly { public: static stackonly getonly() { stackonly obj; return obj; } void print() { cout << "haha" << endl; } private: stackonly() //建構函式私有,防止在外部用new建立物件 {} //拷貝構造就在棧上,所以拷貝構造不用私有 //stackonly(const stackonly&) = delete; }; int main() { stackonly obj = stackonly::getonly(); obj.print(); //stackonly* p = new stackonly; return 0; }
另外還有一種方式,這種方式並不完全正確
方法:只要將new的功能遮蔽掉就可以,遮蔽operator new
class stack
{
public:
stack()
{}
private:
void* operator new(size_t size);
void operator delete(void* p);
};
//stack s3; 在資料段
int main()
{
stack s1;
//stack s2 = new stack;
return 0;
}
這段程式碼中 在全域性區建立的S3物件,S3在資料段,並不在棧上。
單例模式:
一個類只能建立一個物件,即單例模式,該模式可以保證系統中該類只有一個例項,並提供一個訪問它的
全域性訪問點,該例項被所有程式模組共享
例如:在某個伺服器程式中該伺服器的配置資訊存放在一個檔案中,這些配置資料由一個單例物件統一讀取,然後
服務程序中的其他物件再通過這個單例物件獲取這些配置資訊,這種方式簡化了在複雜環境下的配置管理
1.餓漢模式
就是說不管你用不用,程式啟動時就建立一個唯一的例項物件
優點:簡單明瞭,無需關注執行緒安全問題
缺點:如果在一個大環境下使用了過多的餓漢單例,則會生產出過多的例項物件,無論你是否要使用他們
class Singleton
{
public:
static Singleton* GetInstance()
{
return &m_instance;
}
private:
Singleton()
{};
Singleton(const Singleton&) = delete;
Singleton& operator=(Singleton const&);
static Singleton m_instance;
};
Singleton Singleton::m_instance;
int main()
{
Singleton *p1 = Singleton::GetInstance();
return 0;
}
懶漢模式:
如果單例物件構造十分耗時或者佔用很多資源,比如載入外掛,讀取檔案...有可能該物件程式執行時用不到
就要在程式一開始進行初始化,就會導致程式啟動時非常緩慢,這種情況使用懶漢模式(延遲載入)更好
優點:延時載入,用的時候才會產生物件
缺點:需要保證同步,付出效率的代價。
class Singleton
{
public:
static Singleton* Getstance()
{
//加鎖
if (m_pInstance == nullptr)
{
m_mtx.lock();
if (m_pInstance == nullptr)
{
m_pInstance = new Singleton;
}
m_mtx.unlock();
}
return m_pInstance;
}
//實現一個內嵌垃圾回收類
class CGarbo{
public:
~CGarbo(){
if (m_pInstance)
delete m_pInstance;
}
};
//定義一個靜態成員變數,程式結束時,系統會自動呼叫它的解構函式從而釋放單例物件
static CGarbo Garbo;
private:
Singleton(){};
Singleton(const Singleton&) = delete;
Singleton&operator=(const Singleton&) = delete;
static Singleton* m_pInstance;
static mutex m_mtx;
};
Singleton* Singleton::m_pInstance = nullptr;//單例物件指標
mutex Singleton::m_mtx; //互斥鎖
Singleton::CGarbo Garbo;