2012-09-26 58 views
5

我有類A和B.現在我需要編寫一個新的類C,它將在A和B中使用一些字段和方法,但不是全部。 (我將使用A和B中50%的東西)。繼承僅用於代碼重用C++

現在我正在考慮繼承A和B,但是這會讓C包含很多沒有意義的字段和方法。

基本上我只用了代碼重用的目的繼承,否則我將不得不復制和A和B.

粘貼多行代碼,這種做法真的不好?有不同的方法嗎?

謝謝!

+0

謝謝你們的回覆!我非常感謝他們。我考慮使用繼承而不是組合的原因是因爲我還需要修改A和B中的一些行爲。另外,我並不想編輯A和B. – user1657624

回答

2

這是不好的。只有在邏輯上有意義時才使用繼承。

使用成分代替(private繼承的組成形式,但最好還是老派):

class C 
{ 
    A a; 
    B b; 
} 

如果C不是由AB,您還可以保持指針代替,所以C的大小不會增加。

3

繼承應該使用「是」範例。
這意味着C應該繼承自A,B,如果它是A和B的一種。
如果您已經在使用多繼承,您可能需要將A和B分解爲多個類,每個類都處理一小段代碼,然後只從你需要的C繼承C - 這樣C只會佔用它需要的空間(假設A和B有很多成員)。
請記住,您的類的大小不受成員方法影響,只有成員數據。

+1

在C++中,* public *繼承意味着「is-a」 。其他層次的繼承意味着不同的東西......比如「被實現的東西」。 – cHao

+0

@cHao - 這是真的,但即使有私有繼承 - C有權訪問它不需要的代碼部分是一種不好的做法。此外 - 如果A和B有許多數據成員,C的大小仍然會比它應該大。 –

6

繼承沒有「是一半」的概念,所以絕對不是這裏的路。這聽起來像是構圖的一個主要情況。

聽起來好像AB有一個以上的「功能」,因爲他們中的一半都足以組成C

我不知道這是適合你的情況,但考慮打破了分成兩個部分,A1A2與在A1C所需的功能。然後將B轉換爲B1B2。然後

A將是A1A2的組合物,B將是B1B2C的組合物將是A1B1的組合物。他們都沒有任何不必要的功能或數據。

3

由於香草薩特和安德烈Alexandrescu的在他們的著作C++ Coding Standards (item 34),繼承是C++允許你兩個類之間使用最緊密的關係的一個解釋 - 這是僅次於類之間的關係friend

根據S.O.L.I.D principles of OO,一個成功的設計應該旨在寬鬆類之間的耦合 - 這推斷保持依賴關係的最低限度;這又意味着繼承是一個應該謹慎使用的工具。

當然,通常需要依賴關係存在地方,所以一個合理的妥協可以從類中繼承與所有沒有實現(類似於所謂interface S IN的語言,如C#和Java)。例如

class IDriveable 
{ 
public: 
    virtual void GoForward() = 0; 
    virtual void GoBackward() = 0; 
}; 

class Car : public IDriveable { /* etc. */ }; 
class Bus : public IDriveable { /* etc. */ }; 
class Train : public IDriveable { /* etc. */ }; 

通過這種方法,如果有其若干驅動類之間重複使用的代碼元素中,一般會使用組合物或一些其它較弱的關係,以消除重複的代碼。
例如也許你想重用代碼TurnLeftBusCar但不是Train左轉是不合邏輯的,所以TurnLeft可能最終成爲一個單獨的類,它是BusCar的成員。

  • 此外,可能需要了解所有的隱約相關的類是外部類層次結構的任何功能,只知道接口/基而不是基本事實實施細則。

最終的結果可能是少量額外的編寫代碼,但通常是一個不太複雜的設計,通常是一個更容易管理的代碼。設計這樣的代碼沒有任何硬性規則,因爲它完全取決於你試圖解決的獨特問題。

還有其他的方法來重用代碼,而無需緊密耦合太 - 模板可以讓你含蓄地定義接口不含純virtual功能(模板提供額外的類型安全空類 - 這是一個非常的事情,但他們在語法上一個更復雜一點);

還有一些方法可以使用std::function和lambda來重用更具功能性的代碼 - 在傳遞函數對象時通常也沒有緊密的依賴關係。

0

這聽起來像你可以從重構你的代碼中受益:

取而代之的是:

class A 
{ 
    virtual void foo(); 
    virtual void bar(); 
}; 

class B 
{ 
    virtual void biz(); 
    virtual void baz(); 
}; 

class C : public A, public B 
{ 
    virtual void foo() { /* my stuff */ } 
    virtual void biz() { /* my other stuff */ + 

    // but I don't need bar or baz! 
}; 

考慮分拆出來,你用C要A和B的概念上不同的部分:

class core_A 
{ 
    virtual void foo(); 
}; 

class A : public core_A 
{ 
    virtual void bar(); 
}; 

class core_B 
{ 
    virtual void biz(); 
}; 

class B : public core_B 
{ 
    virtual void baz(); 
}; 

class C : public core_A, public core_B 
{ 
    virtual void foo() { /* my stuff */ } 
    virtual void biz() { /* my other stuff */ + 

    // Great, I don't have bar or baz! 
};