我創建了一個抽象類,它只有一組純虛擬方法。有3種不同的類別,這些方法具有具體實現。混合純虛擬和虛擬方法的類
現在,在編寫上述結構之後,我發現派生類中的一些方法具有相同的實現。所以,我將這些功能的邏輯移到了我的基類中,並使它們變爲虛擬而不是純虛擬。現在,實現不需要在派生類中重複。這編譯和執行良好。
我的基類是純虛擬方法和虛擬方法的混合體,是否遵循像這樣的結構是一種很好的設計方法?
我創建了一個抽象類,它只有一組純虛擬方法。有3種不同的類別,這些方法具有具體實現。混合純虛擬和虛擬方法的類
現在,在編寫上述結構之後,我發現派生類中的一些方法具有相同的實現。所以,我將這些功能的邏輯移到了我的基類中,並使它們變爲虛擬而不是純虛擬。現在,實現不需要在派生類中重複。這編譯和執行良好。
我的基類是純虛擬方法和虛擬方法的混合體,是否遵循像這樣的結構是一種很好的設計方法?
是的,那很好。但是:如果這些都是您擁有的類,則不需要使基類實現virtual
。
ITYM,如果這些都是你將有的派生類。 ;-) –
是的,沒有。如果這些類是公共API的一部分,或者可能需要二進制向後兼容性,那麼設計時應考慮到未來('虛擬')。否則,如果需求改變,您可能會在稍後使方法虛擬 –
它的精絕,雖然模式似乎已經出現,你會把所有和僅您純虛函數的類被視爲更大的接口的。
然後,您將定義一個類實現該接口的「常見」部分,並讓您的3個類繼承該類。
隨着時間的推移,它似乎適用於更具擴展性且易於維護的代碼。
Java,出於興趣,非常強制使用這種模式。
顯然,這取決於類之間的關係。換句話說,這是一個設計或實施選擇(即,只要你能合理地證明它)就可以。從技術上講,沒有什麼能夠阻止一個班級混合使用虛擬的,純虛擬的,非虛擬的和靜態的成員函數。
如果兩個派生類重寫繼承的虛函數並以相同的方式實現它,那麼 - 是的 - 我會認真考慮將該函數提供給基類。然而,我會問更多的問題 - 例如,所有派生類是否對默認實現該函數是有意義的。從代碼重用的角度來看,這樣的事情可能是有道理的。從設計的角度來看,它可能不是。也就是說,如果將函數的特定實現視爲「默認」(即,所有派生類默認使用該函數,除非它們覆蓋該函數),那麼將該定義放入一個基類。
的粗例子,你認爲是沒有意義的東西,認爲這
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
(其可能是Hornet
和Tomcat
,但不是Hercules
共用基座)和 - 如果我試圖代表多種類型的貨機的 - 可能是CargoPlane
成爲這些人的共同基礎。然後,Fighter
和CargoPlane
可能來自Aircraft
,但Aircraft
不提供僅對某些類型的飛機纔有意義的功能。附帶說明:雖然有些人聲稱不然,但C++並沒有阻止純虛函數實現定義(實現)。其含義是該函數必須被派生類重寫,但是基類提供了一個默認定義(可以由派生類中的函數顯式調用)。
爲什麼你認爲基類只能有純虛方法? –
是的,那絕對沒問題。它仍然是一個抽象基類,只要它包含一個或多個純虛擬因爲您無法實例化它,但移動常見功能是件好事。 –
如果你真的想保持你的根接口完全純粹(例如:完全隱藏實現在動態工廠庫中的實現),你也可以實現一個從純虛接口繼承的中間BaseImpl,實現公共代碼,重申其餘的純粹虛擬,具體的決賽可以從*繼承*。 – WhozCraig