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