2015-02-12 18 views
0

我有一個基類B和2派生類D1,D2OOP:如何在超類中動態擴展函數

class B { 
    int commonFunc(); 
    virtual int specifyFunc(); 
} 
class D1 : public B { 
    int specifyFunc(); 
} 
class D2 : public B { 
    int specifyFunc(); 
} 

現在我滿足了我需要擴展我的基類功能commonFunc()的要求。因爲我不希望修改現有的代碼在基類派生我另一個類,如:

class B { 
    virtual int commonFunc(); // Change to virtual 
    virtual int specifyFunc(); 
} 
class B2 : public B { 
    int commonFunc(); // A new commonFunc() to meet new requirement 
} 

然而,D1D2不能B2使用新commonFunc()除了我修改繼承層次。

這裏是一個可能的解決方案,我想通了,

class B { 
    virtual int commonFunc(); 
    virtual int specifyFunc(); 
} 
class D1 : public B { 
    int specifyFunc(); 
} 
class D2 : public B { 
    int specifyFunc(); 
} 
class NewD1 : public D1 { 
    int commonFunc(); // Overrided commonFunc() in base class 
} 
class NewD2 : public D2 { 
    int commonFunc(); // Overrided commonFunc() in base class 
} 

由於NewD1NewD2commonFunc()都完全一樣,這個解決方案包括一個貧窮的代碼拷貝

我要找任何設計圖案或者可以動態擴展基類而不需要對現有類進行很多修改的解決方案。

+0

遏制措施如何? B2包含在NewD1和NewD2中。解決方案保留在B2中。 – Jagannath 2015-02-12 04:00:19

+0

*「我不想修改基類中的現有代碼」* - *「對現有類沒有太多修改」* - 那麼,它是什麼?沒有*任何*修改?或沒有*多*修改?請量化「多」。 – 2015-02-12 04:02:37

+0

你需要澄清你的問題或使用一些佔位符僞代碼來幫助我們理解你想要的。 – Pradhan 2015-02-12 04:23:00

回答

2

您有幾種解決方案。繼承只能用於分解具有相同責任的類的代碼。這意味着您的類Car不應該從類Logger繼承,因爲您需要一些日誌記錄功能。這將決定選擇哪種解決方案。

1. D1和D2具有比乙

那麼同樣責任具有更模塊化繼承是圖案decorator的好方法。這可以讓你做你想做的事。只是一個小碼有一個想法:

class B { 
    virtual int commonFunc(); 
    virtual int specifyFunc(); 
} 

class BDecorator: public B { 
    B parent; 
    B(B&); 
    virtual int commonFunc(); // Implementation forward to parent. 
    virtual int specifyFunc(); // Implementation forward to parent. 
} 
class B2: public BDecorator { 
    int commonFunc(); 
    int specifyFunc(); 
} 
class D1 : public BDecorator { 
    int specifyFunc(); 
} 
class D2 : public BDecorator { 
    int specifyFunc(); 
} 

// Use: 
B b(); 
B2 b2(b); 
D1 d1(b2); 

2. D1和D2具有不低於B

相同責任那麼你應該使用成分,而不是繼承的。這意味着您應該定義一個純粹的抽象類D(一個接口),並使其繼承D1D2。然後,在B的構造函數中,您可以注入D。 (是在這個解決方案,你必須改變B中的一點,告訴我,這是一個真正的問題。)

class B { 
    D d; 
    int commonFunc(); 
    virtual int specifyFunc(); // Do something with d. 
    B(D); 
} 

class D { 
    virtual int func(); 
} 
class D1 : public D { 
    int func(); 
} 
class D2 : public D { 
    int func(); 
} 

// Use with B, but you can use B2 (inheriting from B) instead: 
D1 d1(); 
B b1(d1); 

D2 d2(); 
B b2(d2); 

我爲我的舊的C++道歉。

+0

感謝您的詳細解答!這正是我需要的! – LennonLam 2015-02-16 03:56:27

+0

很高興能幫到你! – Gnucki 2015-02-16 07:22:52

0

Interface Design (Program to an interface, not an implementation)

你可以通過使用一個通用的接口(純抽象類)IB避免這種依賴關係的實現。 您可以通過添加新類(NewB)而不更改現有類來更改行爲(commonFunc()) 。
客戶端是指通用接口並且獨立於實現。

Decorator Design

如果你不能做到這一點還是真正希望做的擴展對象的行爲在運行時動態 ,裝飾可能會有幫助。 但裝飾只能在執行舊行爲之前和/或之後添加行爲。

請參閱以下UML圖(如果您不確定如何實施,請告訴我)。

UML Diagram

如需進一步討論,請參閱學習 面向對象的設計&編程/裝飾/設計原則(界面設計) 在http://w3sdesign.com GoF的設計模式記憶。

+0

感謝您的詳細解答!我將使用裝飾器來解決我的問題。再次感謝! – LennonLam 2015-02-16 03:57:03