1. 程式人生 > >effective c++條款32:確定你的public繼承塑模出is-a關係

effective c++條款32:確定你的public繼承塑模出is-a關係

舉書上的例子:

class Bird
{
public:
    void Fly();
};
class Penguin : public Bird
{
};

企鵝也是鳥,但是企鵝並不能飛,也就是說“並不是鳥就能飛”,不滿足is-a關係

再來一個例子:

class Person
{
public:
    void DoGoodThings();
};
class Thief: public Person
{
public:
    void DoGoodThings();//錯誤,賊不做好事
};

賊也是人,但是賊並不幹好事,也就是說“並不是人就幹好事”,不滿足is-a關係

再來:

class Snake
{
public:
    void SendPoison();
};
class WaterSnake: public Snake
{
public:
    void SendPoison();;//錯誤,水蛇無毒
};

水蛇也是蛇,但是水蛇沒有毒,也就是說“並不是蛇就有毒”,不滿足is-a關係

        經過上面的例子,我們可以總結出is-a關係具體的含義: 如果在父類中存在的所有性質,子類完全滿足,那麼就說繼承關係滿足is-a模型;如果在父類中存在的某些性質,子類不能滿足,那麼就說繼承關係不滿足is-a模型。

 注意:is-a模型只限制於public繼承。

如果必須要出現上面形式的繼承,解決方式:

1. 在子類相應的介面中丟擲異常:

class Snake
{
public:
    void SendPoison();
};
class WaterSnake: public Snake
{
public:
    void SendPoison();;//錯誤,水蛇無毒
};
WaterSnake::SendPoison()
{
    //丟擲異常或者提示錯誤資訊
}

 這個解決方式的不好之處在於只有在執行期才能發現水蛇無毒

2. 在父類中不實現不具備一般性的介面:

class Snake
{
public:
};
class WaterSnake: public Snake
{
public:
};

 這樣,如果你寫出如下程式碼:

WaterSnake WS;
WS.SendPoison();

 編譯器就會拒絕讓你通過。

3. 如果有必要,可以再區分有毒的蛇和無毒的蛇,但是這樣的更深層次的繼承體系會更加難以維護。

結論:如果要實現public繼承,就一定要滿足is-a模型。