一、static 與單例模式
單例模式也就是簡單的一種設計模式,它需要:
保證一個類只有一個執行個體,並提供一個全域訪問點
禁止拷貝
C++ Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
|
#include <iostream> using namespace std;class Singleton { public: static Singleton *GetInstance() { if (instance_ == NULL) { instance_ = new Singleton; } return instance_; } ~Singleton() { cout << "~Singleton ..." << endl; } private: Singleton(const Singleton &other); Singleton &operator=(const Singleton &other); Singleton() { cout << "Singleton ..." << endl; } static Singleton *instance_; }; Singleton *Singleton::instance_; int main(void) { //Singleton s1; //Singleton s2;
Singleton *s1 = Singleton::GetInstance(); Singleton *s2 = Singleton::GetInstance(); //Singleton s3(*s1); // 調用拷貝建構函式
return 0; } |
上述程式雖然調用了兩個GetInstance函數,但只調用一次建構函式,即建立一個對象。將賦值運算子和拷貝建構函式聲明為私人,禁止拷貝。但程式存在一個問題就是物件存留期到時不會被析構。
為瞭解決對象不會被析構的問題,可以使用一個靜態嵌套類對象來解決:
C++ Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
|
|
#include <iostream> using namespace std;class Singleton { public: static Singleton *GetInstance() { if (instacne_ == NULL) { instacne_ = new Singleton; } return instacne_; } ~Singleton() { cout << "~Singleton ..." << endl; } //static void Free() //{ // if (instacne_ != NULL) // { // delete instacne_; // } //}
class Garbo { public: ~Garbo() { if (Singleton::instacne_ != NULL) { delete instacne_; } } }; private: Singleton(const Singleton &other); Singleton &operator=(const Singleton &other); Singleton() { cout << "Singleton ..." << endl; } static Singleton *instacne_; static Garbo garbo_; // 利用對象的確定性析構 }; Singleton::Garbo Singleton::garbo_; Singleton *Singleton::instacne_; int main(void) { //Singleton s1; //Singleton s2;
Singleton *s1 = Singleton::GetInstance(); Singleton *s2 = Singleton::GetInstance(); //Singleton s3(*s1); // 調用拷貝建構函式
return 0; } |
利用靜態嵌套對象的確定性析構會調用Garbo類的解構函式,在解構函式內delete 單例類的指標。
上面辦法比較繁瑣,也可以返回局部靜態對象的引用來解決:
C++ Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
|
#include <iostream> using namespace std;class Singleton { public: static Singleton &GetInstance() { static Singleton instance; // 局部靜態對象 return instance; } ~Singleton() { cout << "~Singleton ..." << endl; } private: Singleton(const Singleton &other); Singleton &operator=(const Singleton &other); Singleton() { cout << "Singleton ..." << endl; } }; int main(void) { Singleton &s1 = Singleton::GetInstance(); Singleton &s2 = Singleton::GetInstance(); return 0; } |
局部靜態對象只會初始化一次,所以調用多次GetInstance函數得到的是同一個對象。由於函數內使用了靜態對象,故不是安全執行緒的。實際上也可以使用auto_ptr 智能指標 來解決,程式如下,更詳細的對auto_ptr 的討論參見這裡。
C++ Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
|
#include <iostream> #include<memory> using namespace std;class Singleton { public: static Singleton *GetInstance() { if (instance_.get() == NULL) { instance_ = auto_ptr<Singleton>(new Singleton); } return instance_.get(); } ~Singleton() { cout << "~Singleton ..." << endl; } private: Singleton(const Singleton &other); Singleton &operator=(const Singleton &other); Singleton() { cout << "Singleton ..." << endl; } static auto_ptr<Singleton> instance_; }; auto_ptr<Singleton> Singleton::instance_; int main(void) { //Singleton s1; //Singleton s2;
Singleton *s1 = Singleton::GetInstance(); Singleton *s2 = Singleton::GetInstance(); //Singleton s3(*s1); // 調用拷貝建構函式
return 0; } |
二、const成員函數、const 對象、mutable修飾符
(一)、const 成員函數
const成員函數不會修改對象的狀態
const成員函數只能訪問資料成員的值,而不能修改它
(二)、const 對象
如果把一個對象指定為const,就是告訴編譯器不要修改它
const對象的定義:
const 類名 對象名(參數表);
const對象不能調用非const成員函數
用mutable修飾的資料成員即使在const對象或在const成員函數中都可以被修改。
C++ Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
|
|
#include <iostream> using namespace std;class Test { public: Test(int x) : x_(x), outputTimes_(0) { } int GetX() const { cout << "const GetX ..." << endl; //x_ = 100; return x_; } int GetX() { cout << "GetX ..." << endl; return x_; } void Output() const { cout << "x=" << x_ << endl; outputTimes_++; } int GetOutputTimes() const { return outputTimes_; } private: int x_; mutable int outputTimes_; }; int main(void) { const Test t(10); t.GetX(); Test t2(20); t2.GetX(); t.Output(); t.Output(); cout << t.GetOutputTimes() << endl; return 0; } |
三、const 用法總結
可以對const 的用法做個小總結:
參考:
C++ primer 第四版
Effective C++ 3rd
C++編程規範