友元類的作用

 定義:  
  class   B  
  {  
  private:  
          B()  
          {  
          }  
  friend   class   A;  
  };  
  將導致B無法被除A以外的其它任何class直接繼承以後實例化,也就是說,在上面這個定義的基礎上,如果你在定義:  
          class   C:public   B{};  
  將導致編譯能夠通過,但是無法實例化C(那當然也沒用了,所以間接實現了一個無法繼承的類B),但是因爲A是B的友元,所以能夠進入B的private區域,所以如果定義:  
          class   A:public   B{};  
  能夠實例化A.  
   
  但是這樣定義還有一個漏洞,如果在A普通public繼承B的基礎上再定義:  
          class   D:public   A{};  
  你會發現D也是可以實例化的,那麼相當於間接public繼承了B。這顯然不是我們想要的,所以,正確的做法是(完整代碼):  
   
  class   A;  
  class   B  
  {  
  private:  
          B()  
          {  
          }  
  friend   class   A;  
  };  
   
  class   A:virtual   public   B{};   //A   is   the   one   we're   looking   for  
   
  也就是說要做到三步:  
  1)將你B的相關構造函數放入private區域  
  2)聲明子類A爲B的友元  
  3)定義A爲virtual   public繼承B  
   
  這樣創建的代碼的效果是:  
  B不能被繼承也不能被實例化  
  A可以被實例化,但是不能被繼承  
   
  所以,最後創建出來的A纔是真正我們想要得到的對象

“A可以被實例化,但是不能被繼承”爲什麼不能被繼承???  
  ====================================  
  確切地說,A可以被繼承,但是繼承了A的類不能被實例化(那這個類也就沒用了)。假設有  
        class   E:public   A{};  
  則實例化E時:  
        E   e;  
  系統將報告無法進入B的私有成員聲明而無法通過編譯。  
   
  這是因爲   A是   virtual   繼承   B的,所以,E再繼承A的時候,需要由E去調用B的構造函數,但是E不是B的友元,所以無法編譯通過  
   
  但是如果A不是virtual繼承B的,那麼E再繼承A時,構造函數的調用情況是E調用父類A的構造函數,A再調用A的父類B的構造函數,而A是其父類B的友元,所以這一串調用能夠順利進行。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章