「封裝、繼承、多態」常被稱為面向物件三大特性,但這實際上是 **C++ 對 C 的擴充特性**,而非面向物件思想的本質 (核心是「世界由物件構成」)。本文探討 C++ 繼承機制的內在局限,避免濫用導致設計僵化。
許多教材用「四邊形 → 矩形 → 正方形」繼承鏈示範。直覺認為:
class Quadrangle { ... };
class Rectangle : public Quadrangle { ... };
class Square : public Rectangle { ... };
**悖論**:繼承意味著 **派生類比基類更複雜** (增加新欄位/方法)。但從四邊形到正方形,**約束越來越多、資料越來越少** (四邊形需 4 邊長、矩形需寬高、正方形只需邊長)。繼承方向與複雜度演進 **背道而馳**。
「在沒有給定需求場景的情況下,永遠無法設計出一個類,更別說類之間的層次關係。」
若需求僅為「取邊長、算面積」,三個類應 **獨立實作**,各自最優化:
class Quadrangle { int GetSide(int idx); int Area(); int sides[4]; };
class Rectangle { int Width(); int Height(); int Area(); int w, h; };
class Square { int Width(); int Area(); int w; };
繼承機制 (Implementation Inheritance) 與 **介面機制** (Interface Inheritance) 是兩碼子事。C++ 用純虛擬類別模擬介面:
class IShape { virtual int Area() = 0; virtual ~IShape() {} };
class Quadrangle : public IShape { ... };
class Rectangle : public IShape { ... };
class Square : public IShape { ... };
→ **介面描述「是什麼」 (分類學);實作繼承描述「如何實作」 (程式碼復用)。勿混淆。**
視窗與控制項本質不同,微軟為復用訊息機制強行讓所有控制項繼承 CWnd,導致:
教訓:程式碼復用是良好設計的**副產品**,而非設計目的。**
has-a 比 is-a 更靈活、耦合更低。std::vector → MyVector 加入邊界檢查)。1. 繼承機制有嚴重局限,難描述現實分類層次。
2. 別生搬硬套現實「是一種」關係進繼承體系。
3. 純為程式碼復用而繼承是反模式,優先用組合/介面。
4. 介面 ≠ 繼承,C++ 用純虛類別實作介面,但兩者本質不同。