C++設計實現一個不能被繼承的類

  C++不一樣於Java,Java中被final關鍵字修飾的類不能被繼承,C++能實現不被繼承的類,可是須要本身實現。程序員

  爲了使類不被繼承,最好的辦法是使子類不能構造父類的部分,此時子類就沒法實例化整個子類。在C++中,子類的構造函數會自動調用父類的構造函數,子類的析構函數也會自動的調用父類的析構函數,因此只要把類的構造函數和析構函數都定義爲private()函數,那麼當一個類試圖從他那兒繼承時,必然會因爲試圖調用構造函數、析構函數而致使編譯錯誤。此時該類即不能被繼承。函數

  但由此會形成一個問題,private的構造函數與析構函數沒法獲得該類的實例,此時能夠經過定義靜態類來建立和釋放類的實例。spa

  程序示例以下:設計

  

 1 class FinalClass1
 2 {
 3     public:
 4         static FinalClass1* GetInstance()
 5         {
 6             return new FinalClass1;
 7         }
 8 
 9         static void DeleteInstance(FinalClass1* pInstance)
10         {
11             delete pInstance;
12             pInstance = 0;
13         }
14 
15     private:
16         FinalClass1(){}
17         ~FinalClass1(){}
18 };        

  在上例中,FinalClass1這個類是不能被繼承的,可是經過這個方法獲得的實例都位於堆上,須要程序員手工釋放。code

  考慮到這個侷限性,設計以下一個類。blog

  

 1 template <typename T> class MakeFinal
 2 {
 3         friend T;
 4     private:
 5         MakeFinal(){}
 6         ~MakeFinal(){}
 7 };
 8 
 9 class FinalClass2 : virtual public MakeFinal<FinalClass2>
10 {
11     public:
12         FinalClass2(){}
13         ~FinalClass2(){}
14 };

  上例中的FinalClass2類使用起來與通常的類沒有任何區別,既能夠在棧上,也能夠在堆上建立實例。而MakeFinal <FinalClass2>的構造函數和析構函數都是私有的,但因爲類FinalClass2是它的友元函數,所以在FinalClass2中調用MakeFinal <FinalClass2>的構造函數和析構函數也不會形成編譯錯誤。繼承

  對於FinalClass2類而言,繼承一個類並建立它的實例時,他會出現編譯錯誤。程序代碼示例以下:編譯

1 class Try : public FinalClass2
2 {
3     public:
4         Try(){}
5         ~Try(){}
6 };
7 
8 Try temp;

  因爲FinalClass2是從類MakeFinal <FinalClass2>虛繼承過來的,在調用Try的構造函數時,會直接跳過FinalClass2,而直接調用MakeFinal <FinalClass2>的構造函數。但因爲類Try不是MakeFinal<FinalClass2>的友元,所以不能調用其私有的構造函數。因此,試圖從FinalClass2繼承的類,一旦實例化,都會致使編譯錯誤,所以FinalClass2不能被繼承。class

相關文章
相關標籤/搜索