不能被繼承的類

題目:用C++設計一個不能被繼承的類.
 
常規的解法:把構造函數設爲私有函數
咱們經過定義共有的靜態函數來建立和釋放類的實例。
 class SealedClass1
{
  public:
   static SealedClass1* GetInstance()
   {return new SealedClass1();}
   static void DeleteInstance(SealedClass1* pInstance)
   {delete pInstance;}
   private:
   SealedClass1(){}
   ~SealedClass1(){}
};
 這個類是不能被繼承,但總以爲它和普通的類型有些不同,使用起來有點不方便.好比咱們只能獲得位於堆上的實例,而得不到位於棧上的實例。
 
新奇的解法:利用虛擬繼承,能給面試官留下很好的印象
 template<typename T> class MakeSealed
 {
  friend T;
  private:
  MakeSealed() {}
  ~MakeSealed(){}
 }
 
class SealedClass2: virtual public MakeSealed<SealedClass2>
{
 public:
 SealedClass2(){}
 ~SealedClass2(){}
};
 
 這個SealedClass2使用起來和通常的類型沒有多大差異,咱們能夠在棧上、也能夠在堆上建立實例。儘管類MakeSealed<SealedClass2>的構造函數和析構函數都是私有的,
 但因爲類SealedClass2是它的友元類型,所以在SealedClass2中調用MakeSealed<SealedClass2>的構造函數和析構函數都不會引發編譯錯誤.
 但當咱們試圖從SealedClass2中繼承一個類並建立它的實例的時候,卻不可以經過編譯。好比當咱們從SealedClass2中繼承出類型Try:
  class Try: public SealedClass2
 {
  public:
  Try(){}
  ~Try(){}
 };
 
 因爲類SealedClass2是從類MakeSealed<SealedClass2>虛繼承過來的,在調用Try的構造函數的時候,會跳過SealedClass2而直接調用MakeSealed<SealedClass2>的構造函數.
 很是遺憾的是Try不是MakeSealed<SealedClass2>的友元類型,所以不能調用它的私有構造函數.
 經過上面的分析,咱們發現從SealedClass2繼承的類,一旦實例化就會致使編譯出錯,所以SealedClass2不能被繼承,這也就知足了題目的要求.
相關文章
相關標籤/搜索