2010年8月30日 星期一

pure virtual function 與 abstract base class

有些時後會發生一種情況,我們必須創立許多類似的類別,而這些類別必須有某些相同且必要的條件,同樣以遊戲為例,例如資深工程師制訂了 NPC 的規格,各工程師照著規格實作遊戲企劃人員構想的各種 NPC 這種情況可以用到 virtual function 來解決各衍生類別的同名異式,但無法要求衍生類別一定要實作某些類別的內容,這時可以利用 "pure virtual function(純虛擬函式)" 例如:


class CNPC
{
  public:
  int Attack() const = 0;
};


在原型的尾端接上 = 0 ,就可以使其成為純虛擬函數,若一個類別中含有 pure virtual function,它是無法用來產生物件的,此種類別只能被當作基底類別,即使我們有在實作檔案中定義詳細的內容,抽象基礎類別 (abstract base class) 即是這類的應用。

若資深工程師定義了一個詳細的NPC基底類別讓其他工程師繼承,他除了要將函數宣告為純虛擬函數外,還有一項重點要注意,他可能必須適時的使用 protected 關鍵字。

大部份的時間我們只會用到 private 與 public 來區分類別成員的保護性,但所有衍生類別卻只能透過基底類別的公用函數來存取 private member 實務上並不方便,也非必要,因為基底類別並沒辦法用來宣告,所以我們可以將一些 member variable 宣告為 protected 成員,使其成為衍生類別的 private member。

例如:


class CNPC
{
private:
  int m_nHP;
  int m_nMP;
protected:
  void Sleep() const = 0;
public:
  int Attack() const = 0;
};


NPC 的休息動作、HP 回復速度等內容要求衍生類別必須自行定義,利用 protected 宣告此函數,如此衍生 NPC 即可擁有私有的休息函數,又可以達到外界又無法呼叫此休息函數,僅由類別內自己控制。

若此 Sleep() 沒有宣告為 protected 而是宣告為 private member,那麼 CNPC 就必須要提供一個 public function 讓衍生類別間接呼叫休息函數,可以做到同樣的效果,但較為麻煩且不必要。

對於需要制訂清楚的規則與關係時,abstract base class 設計是個不錯的方法。

沒有留言:

張貼留言