首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

面向對象語言理論(二):子類型多態、動態分派、RTTI 與協變/反協變

     編輯:關於C++

4. Subsumption 與 Dynamic Dispatch

Subsumption 規則

若 c' subclass c 且 o': InstanceTypeOf(c'),則 o': InstanceTypeOf(c)。拆解為:

  1. Subsumption:a: A, A <: B ⇒ a: B(子類型判斷唯一標準)。
  2. Subclassing-is-Subtyping:InstanceTypeOf(c') <: InstanceTypeOf(c) ⇔ c' subclass c。

所有 OO 語言支持 Subsumption;大多數不區分子類化與子類型,少數新語言分離二者(類似 C++ 私有繼承但更豐富)。

動態分派 vs 靜態分派

procedure f(x: InstanceTypeOf(cell)) {
    x.set(3);  // 調用 cell.set 還是 reCell.set?
}
f(myReCell);  // myReCell: InstanceTypeOf(reCell)
  • Static Dispatch:編譯期按聲明類型綁定(cell.set)。
  • Dynamic Dispatch:運行期按對象真實類型綁定(reCell.set),需對象內部狀態不變(無對象切片)。

C++ 虛函數表實現動態分派,指針調整可能發生但語義保持對象身份不變。

5. 賽翁失馬:類型信息遺失與 RTTI

Subsumption 導致靜態類型信息遺失:將 MyObject 視為 Object 只能訪問基類接口。純粹派主張僅用動態分派操作遺失成員,但現實語言提供 RTTI:

  • C++: dynamic_cast
  • Java: instanceof

RTTI 缺點

  1. 破壞抽象,暴露不應使用的內部結構。
  2. 運行期類型不確定性增加脆弱性。
  3. 最嚴重:新增子類需修改所有 dynamic_cast/instanceof 站點,編譯器無法協助,缺乏擴展性。

運行開銷非核心問題,方法論缺陷才是關鍵。類型系統演進多源於避免 RTTI(如 Self 類型、協變返回類型)。

6. 協變、反協變、不變

構造類型參數位置變化性規則
Pair A×B返回類型協變A' <: A ⇒ A'×B <: A×B
Function B→A參數類型反協變B' <: B ⇒ (B→A) <: (B'→A)
Function B→A返回類型協變A' <: A ⇒ (B→A') <: (B→A)
Function A→A參數+返回不變無子類型關係

可變容器(如 setA(A))導致不變性,函數式不可變數據結構天然協變。

7. 方法特化

覆寫方法允許:

  • 返回類型 協變(子類型返回更具體類型)。
  • 參數類型 反協變(子類型接受更寬泛類型)。
class c {
    method m(x: A): B ...
}
subclass c' of c {
    method m(x: A'): B' ...  // 合法若 A <: A' 且 B' <: B
}

此規則保證類型安全:調用者按父類簽名傳參,子類方法能處理更寬參數;調用者期望父類返回類型,子類返回更具體類型符合預期。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved