2017-01-10 112 views
1

我創建了一個抽象類,它只有一組純虛擬方法。有3種不同的類別,這些方法具有具體實現混合純虛擬和虛擬方法的類

現在,在編寫上述結構之後,我發現派生類中的一些方法具有相同的實現。所以,我將這些功能的邏輯移到了我的基類中,並使它們變爲虛擬而不是純虛擬。現在,實現不需要在派生類中重複。這編譯和執行良好。

我的基類是純虛擬方法和虛擬方法的混合體,是否遵循像這樣的結構是一種很好的設計方法?

+1

爲什麼你認爲基類只能有純虛方法? –

+0

是的,那絕對沒問題。它仍然是一個抽象基類,只要它包含一個或多個純虛擬因爲您無法實例化它,但移動常見功能是件好事。 –

+2

如果你真的想保持你的根接口完全純粹(例如:完全隱藏實現在動態工廠庫中的實現),你也可以實現一個從純虛接口繼承的中間BaseImpl,實現公共代碼,重申其餘的純粹虛擬,具體的決賽可以從*繼承*。 – WhozCraig

回答

0

是的,那很好。但是:如果這些都是您擁有的類,則不需要使基類實現virtual

+2

ITYM,如果這些都是你將有的派生類。 ;-) –

+1

是的,沒有。如果這些類是公共API的一部分,或者可能需要二進制向後兼容性,那麼設計時應考慮到未來('虛擬')。否則,如果需求改變,您可能會在稍後使方法虛擬 –

5

它的精絕,雖然模式似乎已經出現,你會把所有純虛函數的類被視爲更大的接口的。

然後,您將定義一個類實現該接口的「常見」部分,並讓您的3個類繼承該類。

隨着時間的推移,它似乎適用於更具擴展性且易於維護的代碼。

Java,出於興趣,非常強制使用這種模式。

1

顯然,這取決於類之間的關係。換句話說,這是一個設計或實施選擇(即,只要你能合理地證明它)就可以。從技術上講,沒有什麼能夠阻止一個班級混合使用虛擬的,純虛擬的,非虛擬的和靜態的成員函數。

如果兩個派生類重寫繼承的虛函數並以相同的方式實現它,那麼 - 是的 - 我會認真考慮將該函數提供給基類​​。然而,我會問更多的問題 - 例如,所有派生類是否對默認實現該函數是有意義的。從代碼重用的角度來看,這樣的事情可能是有道理的。從設計的角度來看,它可能不是。也就是說,如果將函數的特定實現視爲「默認」(即,所有派生類默認使用該函數,除非它們覆蓋該函數),那麼將該定義放入一個基類。

的粗例子,你認爲是沒有意義的東西,認爲這

class Aircraft 
    { 
     public: 
      virtual void Manoeuvre() = 0; 
    }; 

    class Hornet : public Aircraft // F/A-18 hornet fighter aircraft 
    { 
     public: 

       void Manoeuvre(); 
    }; 

    class Tomcat : public Aircraft // F-14 tomcat fighter aircraft 
    { 
     public: 

       void Manoeuvre(); 
    }; 

假設,因爲我們的模型的保真度,這兩個派生類有相同的Manoeuvre()功能 - 他們都是超音速戰鬥機(所以可能採用類似的機動風格,儘管具有不同的參數化)。但是,這還不夠他們Manoeuvre()功能移到基類,因爲有飛機不屬於超音速戰鬥機,如

class Hercules : public Aircraft // C-130 hercules cargo plan 
    { 
     public: 

       void Manoeuvre(); 
    }; 

在這種情況下,它沒有任何意義了Hercules繼承機動超音速戰鬥機的能力,反之亦然。所以這是由Aircraft類提供的。

在這種情況下,我可以考慮引入中間類,如Fighter(其可能是HornetTomcat,但不是Hercules共用基座)和 - 如果我試圖代表多種類型的貨機的 - 可能是CargoPlane成爲這些人的共同基礎。然後,FighterCargoPlane可能來自Aircraft,但Aircraft不提供僅對某些類型的飛機纔有意義的功能。附帶說明:雖然有些人聲稱不然,但C++並沒有阻止純虛函數實現定義(實現)。其含義是該函數必須被派生類重寫,但是基類提供了一個默認定義(可以由派生類中的函數顯式調用)。