2016-08-29 154 views
1

考慮我有一系列派生類例如以下所列:繼承和成員函數

class A 
{ 
... 
} 

class B1 : public A //there may be many B's here say, B2, B3 etc 
{ 
... 
} 
class C1 : public B1 //may be more C's as well 
{ 
... 
} 

我想把所有在單個容器中的對象的,因此,所有的將類型類A的。

假設我想爲類C1添加一個函數,那麼最好的方法是什麼?我的選擇是在基類A中引入它,並在C1中寫入所需的實現,或者,我可以在C1中引入它並進行動態轉換以訪問它。哪一個是首選?動態鑄造是否太昂貴? (我的主要約束是運行時間。我在基類中有一個標誌來指示它是什麼類型的派生對象,因此我不必動態地轉換容器中的每個對象。是否將不必要的函數添加到基類會導致?在惡劣的指令高速緩存使用)

+4

沒有人能告訴你動態鑄造是否「太貴」,因爲你可以負擔得起的是主觀的。由於這看起來就是你所追求的(「我的主要約束就是運行時間」),我會建議這樣做,並對結果進行基準測試,看看它是否對於特定的硬件和編譯器優化和用例來說太昂貴,外部限制和... – Altainia

+2

使接口太廣泛是糟糕的設計,因此是向下廣播,您可能需要一個指向更多特定接口的額外集合。 – imreal

+0

您可以使用具有訪問者模式的「變體」。 – AndyG

回答

2

你不告訴我們,新功能的目的C1,這影響答案,但粗糙的準則:

  • 如果新功能是你可能需要的任何對象的一般行爲,而C1恰好是第一個用戶,絕對只需將接口添加到A即可。
  • 如果新的功能是特定於C一系列類它可以遵循一些一般模式(例如後處理)中,添加一個post_process方法A,在C1覆蓋它,並有方法調用C1的私有實現方法來執行實際的特定後處理任務。
  • 如果這兩種情況都不是這種情況,那麼您可能希望重新考慮您對繼承的使用,因爲您可能會使用它來表示除替換之外的其他關係。
+0

由於私有數據的類型,只能在'C1'中執行新函數它有權訪問並且不被頻繁調用。 – user6386155

0

添加虛擬函數的基類更好,因爲:

  • 你應該避免尤其是在性能敏感的代碼動態轉換。請參閱Performance of dynamic_cast?

  • 在執行特定於類型的操作之前,您應該避免有條件檢查對象類型(例如,是A,B1還是C1?)。不僅因爲它很慢,而且因爲如果你這樣做,每次添加一個新的對象類型(例如C2),你都需要檢查所有這些條件,看看它們是否需要更新。