78 10. Inheritance in C++ 我 們 已 介 紹 了 物 件 導 向 程 式 的 第 一 個 主 要 特 性, 即 程 式 可 模 組 化 成 為 類 別 ( 物 件 ), 類 別 具 有 資 料 封 裝 的 特 性 接 下 來 我 們 要 介 紹 物 件 導 向 程 式 的 另 一 個 主 要 特 性, 那 就 是 類 別 具 有 繼 承 的 功 能 繼 承 就 是 重 複 使 用 程 式, 將 現 有 的 類 別 的 屬 性 與 行 為, 加 以 修 改 或 重 新 定 義 (overridden), 即 可 製 作 出 新 的 類 別, 達 到 軟 體 再 使 用 的 目 標 當 我 們 要 產 生 一 個 新 類 別, 如 其 與 某 一 個 已 經 定 義 好 的 類 別 性 質 有 許 多 相 似 之 處, 只 有 部 分 不 同 需 修 改 或 加 強, 我 們 可 以 不 需 以 重 新 製 作 的 方 式 來 定 義 這 個 新 類 別 的 資 料 成 員 與 函 式 成 員, 只 需 使 用 繼 承 的 功 能, 指 定 其 去 繼 承 此 一 已 經 定 義 好 的 類 別 ( 基 本 類 別, base class), 經 由 繼 承 某 基 本 類 別 來 產 生 的 新 類 別 稱 為 其 之 衍 生 類 別 (derived class) 衍 生 類 別 會 繼 承 基 本 類 別 所 有 的 資 料 成 員 與 函 式 成 員, 當 繼 承 而 來 的 函 式 成 員 不 適 於 衍 生 類 別 時, 就 可 以 在 衍 生 類 別 之 定 義 內 將 其 重 新 定 義 (overridden), 並 可 進 一 步 加 入 新 的 成 員 ( 資 料 或 函 式 ), 以 符 合 衍 生 類 別 應 有 的 屬 性 與 行 為 繼 承 功 能 真 正 強 大 之 處, 在 於 我 們 可 以 在 衍 生 類 別 裡 定 義 基 本 類 別 所 沒 有 的 資 料 及 功 能, 或 取 代 改 良 繼 承 自 基 本 類 別 的 功 能, 將 其 功 能 增 強 取 代 和 改 良 換 句 話 說, 衍 生 類 別 通 常 會 增 加 屬 於 他 自 己 的 資 料 成 員 與 函 式 成 員, 故 衍 生 類 別 一 般 都 比 其 基 本 類 別 要 來 的 大, 但 對 的 其 也 變 的 比 較 特 別 化, 所 能 表 示 的 物 件 範 圍 較 為 狹 隘 每 一 個 經 由 繼 承 產 生 的 衍 生 類 別 又 可 以 被 繼 承 成 為 其 下 衍 生 類 別 的 基 本 類 別, 此 外, 對 於 C++, 一 個 衍 生 類 別 可 以 繼 承 一 個 以 上 的 基 本 類 別, 故 C++ 之 類 別 繼 承 為 階 層 式 的 交 錯 樹 狀 架 構 C++ 提 供 了 三 種 繼 承 方 式,public protected 與 private, 我 們 主 要 將 介 紹 public 繼 承 (public inheritance), 並 簡 要 說 明 其 他 兩 種 繼 承 對 於 public 繼 承, 衍 生 類 別 的 每 一 個 物 件 也 可 視 為 其 基 本 類 別 的 物 件, 但 是, 基 本 類 別 的 物 件 則 不 是 衍 生 類 別 的 物 件 對 於 物 件 間 的 關 係, 主 要 有 is a 和 has a 關 係 之 設 計 ; is a 關 係 就 是 繼 承, 衍 生 類 別 之 物 件 也 可 視 為 其 基 本 類 別 的 物 件 ; has a 關 係 就 是 合 成, 意 指 某 類 別 之 物 件 使 用 其 他 類 別 的 物 件 做 其 成 員
79 10.1 Base Class and Derived Classes 一 類 別 的 物 件 常 常 也 可 視 為 另 一 類 別 的 物 件 ( 其 中 一 種 或 其 下 分 支 ), 例 如, 研 究 生 是 學 生 的 一 種, 我 們 可 利 用 繼 承 的 功 能, 將 學 生 定 義 為 基 本 類 別, 而 將 研 究 生 定 義 為 學 生 的 衍 生 類 別 衍 生 類 別 的 每 一 個 物 件 同 時 也 屬 於 此 類 別 之 基 本 類 別 的 物 件, 但 反 之 並 不 成 立 基 本 類 別 的 物 件 並 不 是 此 類 別 之 衍 生 類 別 的 物 件 例 如, 在 繼 承 的 關 係 上, 研 究 生 是 學 生 的 一 種 特 殊 類 型, 反 之 學 生 並 不 一 定 是 研 究 生, 語 意 上 是 如 此, 也 為 類 別 繼 承 的 規 則 有 時, 基 本 類 別 又 稱 為 父 類 別, 衍 生 類 別 又 稱 為 子 類 別 有 關 於 基 本 類 別 與 衍 生 類 別 的 例 子 如 下 : Base Class Derived Class + Base Class Derived Class Student GraduateStudent MasterStudent PhDStudent UndergraduateStudent FullTimeStudent PartTimeStudent Shape 2DShape Circle Triangle Rectangular 3DShape Sphere Cube Vehicle Car Bus Employee ContractEmployee HourlyEmployee Account SavingAccount CheckingAccount Matrix FullMatrix SymmetricMatrix SparseMatrix Element TrussElement BeamElement BeamColumnElement PlateElement
80 類 別 繼 承 為 階 層 式 的 交 錯 樹 狀 架 構, 一 類 別 可 如 先 前 獨 立 存 在, 但 如 其 位 於 繼 承 的 架 構 中, 則 其 不 是 提 供 本 身 屬 性 與 行 為 給 其 下 類 別 的 基 本 類 別, 就 是 繼 承 其 他 類 別 屬 性 與 行 為 之 衍 生 類 別, 或 二 者 皆 是 單 一 繼 承 (single inheritance) 是 指 一 個 衍 生 類 別 是 由 繼 承 單 一 個 基 本 類 別 而 來 如 一 衍 生 類 別 繼 承 了 多 個 基 本 類 別, 則 稱 為 多 重 繼 承 (multiple inheritance) UniversityMember Employee Student Faculty Staff GraduateStudent UndergraduateStudent Administrator Teacher T A R A AdministratorTeacher public 繼 承 的 格 式 如 下 : class Y : public X 新 增 之 資 料 成 員 ; public: 新 增 或 重 新 定 義 之 函 式 成 員 ;
81 衍 生 類 別 會 繼 承 基 本 類 別 所 有 的 資 料 成 員 與 函 式 成 員 ( 需 注 意 這 些 成 員 並 沒 有 出 現 於 衍 生 類 別 的 程 式 碼 中, 易 弄 混 ), 於 public 繼 承 的 情 況 下, 衍 生 類 別 之 函 式 成 員 只 能 直 接 存 取 或 呼 叫 所 繼 承 來 的 public 與 protected 成 員, 但 不 能 直 接 存 取 或 呼 叫 所 繼 承 來 的 private 成 員 通 常 會 有 多 個 衍 生 類 別 所 共 同 繼 承 自 一 基 本 類 別 的 情 形, 則 這 些 衍 生 類 別 同 屬 於 基 本 類 別 之 一 類, 例 如, 研 究 生 與 大 學 生 都 屬 於 學 生 我 們 可 將 這 些 衍 生 類 別 所 共 有 的 資 料 與 功 能, 定 義 於 基 本 類 別, 如 此 衍 生 類 別 們 就 不 必 對 這 些 共 有 的 部 分 個 別 重 複 定 義, 例 如, 將 研 究 生 與 大 學 生 都 有 的 姓 名 與 學 號 定 義 於 學 生 基 本 類 別 內 而 特 屬 於 衍 生 類 別 之 屬 性 與 行 為 則 定 義 於 衍 生 類 別, 例 如, 將 研 究 生 才 有 之 組 別 與 研 究 室 定 義 於 研 究 生 衍 生 類 別 衍 生 類 別 繼 承 自 基 本 類 別 的 的 public 函 式 成 員, 可 能 會 不 符 合 衍 生 類 別 的 需 要, 故 我 們 可 以 在 衍 生 類 別 內 修 改 或 重 新 定 義 (overridden) 這 些 函 式 成 員, 使 之 合 乎 衍 生 類 別 應 有 的 之 意 義 與 行 為 衍 生 類 別 中 函 式 成 員 之 重 新 定 義, 常 會 先 呼 叫 已 定 義 於 基 本 類 別 的 public 函 式 成 員, 再 加 上 專 屬 於 此 衍 生 類 別 的 部 分 ; 或 者, 完 全 將 此 函 式 成 員 重 新 定 義 亦 可 故 繼 承 同 一 基 本 類 別 之 類 別 的 共 同 處 即 基 本 類 別 之 屬 性 與 行 為, 經 由 public 繼 承 所 產 生 的 任 何 衍 生 類 別 之 物 件, 均 同 時 亦 為 基 本 類 別 的 物 件 ( 當 物 件 以 指 標 或 參 考 操 作 時 ), 因 為 對 外 部 程 式 而 言, 其 完 全 具 有 基 本 類 別 應 有 的 屬 性 與 行 為, 且 存 取 權 限 與 基 本 類 別 之 設 定 完 全 相 同 但 基 本 類 別 之 物 件 並 非 衍 生 類 別 之 物 件, 因 為 衍 生 類 別 通 常 有 屬 於 此 衍 生 類 別 獨 有 的 屬 性 與 行 為 例 : 當 Manager 以 public 繼 承 了 Employee,Employee* 可 指 到 並 操 作 Manager 物 件 Manager * Mptr = new Manager (. ); Employee * Eptr = Mptr; 以 下 則 程 式 則 不 可 被 編 譯 器 接 受 Employee * Eptr = new Employee (. ); Manager * Mptr = Eptr;
82 10.1.1 Constructor and Destructor for a Derived Class 基 本 類 別 之 建 構 函 式 解 構 函 式 與 拷 貝 指 定 運 算 子 不 會 繼 承 給 衍 生 類 別 不 過 衍 生 類 別 之 建 構 函 式 解 構 函 式 與 拷 貝 指 定 運 算 子, 可 以 呼 叫 基 本 類 別 之 建 構 函 式 解 構 函 式 與 拷 貝 指 定 運 算 子 衍 生 類 別 通 常 需 定 義 自 己 的 建 構 函 式, 衍 生 類 別 的 建 構 函 式, 必 須 要 呼 叫 其 每 個 基 本 類 別 的 建 構 函 式, 來 初 始 化 繼 承 自 基 本 類 別 的 資 料 成 員, 明 確 地 呼 叫 基 本 類 別 的 建 構 函 式, 其 格 式 如 下, 如 未 明 確 地 呼 叫, 則 會 自 動 呼 叫 基 本 類 別 之 預 設 建 構 函 式 class Employee char* name; int deptid; public: Employee(char* n, int d) strcpy(name, n); deptid = d; print( );. ; class Manager : public Employee int rank;. public: Manager(char* n, int d, int r) : Employee(n, d), // initialize base members rank ( r ) // initialize local members print( ); // override print.
83 衍 生 類 別 物 件 之 建 立 的 程 序 是 :(1) 先 呼 叫 基 本 類 別 之 建 構 函 式 初 始 化 繼 承 來 的 base members,(2) 之 後 執 行 衍 生 類 別 之 member initializer,(3) 最 後 執 行 建 構 函 式 中 之 內 容 來 設 定 local members 至 於 解 構 函 式 方 面, 在 執 行 完 衍 生 類 別 的 解 構 函 式 中 的 命 令 後, 系 統 必 定 會 自 動 呼 叫 其 基 本 類 別 的 解 構 函 式 故 衍 生 類 別 物 件 之 釋 放 為 與 物 件 建 立 相 反 的 程 序,(1) 先 釋 放 local members,(2) 然 後 執 行 基 本 類 別 之 解 構 函 式 釋 放 base members 10.1.2 Calling/Accessing the Base Members from Derived Classes 衍 生 類 別 的 函 式 成 員 可 以 存 取 或 呼 叫 繼 承 自 基 本 類 別 的 public 或 protected 資 料 成 員 或 函 式 成 員, 其 做 法 是 使 用 基 本 類 別 的 名 稱 與 範 圍 解 析 運 算 子, 例 如 : void Employee::print( ) cout<<name<< <<deptid<<endl; void Manager::print( ) Employee::print( ); cout<<rank<<endl; //calling base member 10.1.3 Overriding the Function Members from Derived Classes 由 基 本 類 別 繼 承 來 的 函 式 成 員, 常 不 符 基 本 類 別 的 需 要 衍 生 類 別 可 將 繼 承 自 基 本 類 別 的 函 式 成 員, 依 衍 生 類 別 的 需 要 修 改 或 重 新 定 義, 稱 為 override, 其 做 法 是 我 們 須 於 衍 生 類 別 中 重 新 宣 告 此 一 繼 承 來 的 函 式 成 員, 並 提 供 其 新 的 定 義, 例 如 上 例 之 print Override 的 做 法, 可 先 呼 叫 基 本 類 別 中 被 overridden 的 函 式 成 員, 再 補 充 屬 於 衍 生 類 別 的 內 容, 如 上 例 之 print; 或 完 全 重 新 定 義, 如 需 存 取 基 本 類 別 的 private members, 需 有 public 或 protected 的 存 取 函 式
84 程 式 範 例 : oop_ex93.cpp 1. circle 類 別 以 public 的 方 式 繼 承 了 point 類 別, 這 項 指 定 出 現 於 circle 類 別 定 義 的 第 一 行, 冒 號 (:) 代 表 了 繼 承 2. 衍 生 類 別 (circle) 會 繼 承 所 有 基 本 類 別 (point) 的 成 員 (x, y, moveto, distto, print ), 但 於 衍 生 類 別 的 建 構 函 式 中, 無 法 直 接 存 取 基 本 類 別 的 私 有 成 員 (x, y), 為 了 對 繼 承 自 基 本 類 別 的 私 有 成 員 初 始 化, 必 須 要 使 用 基 本 類 別 的 建 構 函 式, 呼 叫 格 式 見 範 例 至 於 呼 叫 順 序, 是 基 本 類 別 的 建 構 函 式 先 被 呼 叫, 再 執 行 衍 生 類 別 的 建 構 函 式 3. 衍 生 類 別 可 以 直 接 使 用 繼 承 而 來 的 public 函 式 成 員 ( 如 moveto, distto), 並 定 義 專 屬 於 衍 生 類 別 的 新 函 式 成 員 ( 如 area, perimeter, getr) 4. 於 衍 生 類 別 中, 如 果 要 存 取 基 本 類 別 之 私 有 成 員, 唯 有 透 過 基 本 類 別 所 提 供 的 函 式 成 員 ( 例 如 getx, gety), 如 基 本 類 別 沒 有 提 供 這 些 存 取 函 式, 則 無 法 達 成 5. 如 需 要 將 繼 承 自 基 本 類 別 的 函 式 成 員, 依 衍 生 類 別 的 需 要 修 改 或 重 新 定 義 ( 例 如 print), 則 我 們 須 於 衍 生 類 別 中 重 新 宣 告 此 一 函 式 成 員, 並 提 供 其 新 的 定 義, 修 改 或 重 新 定 義 後 的 函 式 將 於 衍 生 類 別 中 取 代 繼 承 自 基 本 類 別 的 定 義 6. 如 果 對 某 一 繼 承 自 基 本 類 別 的 函 式 成 員, 我 們 不 需 完 全 更 改 其 原 本 的 定 義, 只 需 要 加 入 新 的 功 能 ( 例 如 print), 我 們 可 以 不 必 重 寫 已 定 義 於 原 基 本 類 別 之 原 函 式 的 部 分, 而 只 要 呼 叫 此 一 原 函 式, 再 加 上 新 增 的 部 分 即 可 7. 在 執 行 完 衍 生 類 別 的 解 構 函 式 中 的 命 令 後, 系 統 必 定 會 自 動 呼 叫 其 基 本 類 別 的 解 構 函 式, 因 此, 於 衍 生 類 別 的 解 構 函 式 中, 不 需 對 繼 承 自 其 基 本 類 別 的 資 料 成 員 做 處 理, 此 項 工 作 就 交 給 基 本 類 別 的 解 構 函 式 至 於 呼 叫 順 序, 是 衍 生 類 別 的 構 函 式 先 被 呼 叫, 再 執 行 基 本 類 別 的 構 函 式 程 式 範 例 : oop_ex94.cpp 1. 一 衍 生 類 別 可 以 當 作 是 其 基 本 類 別 來 使 用, 例 如 : 將 一 衍 生 類 別 物 件 指 定 給 其 基 本 類 別 的 指 標 參 考, 或 是 當 作 參 數, 輸 入 接 受 其 基 本 類 別 的 函 式 內 ( 可 參 考 之 後 將 介 紹 的 衍 生 類 別 之 拷 貝 建 構 函 式 與 拷 貝 指 定 運 算 子 ) 2. 此 之 所 以 可 行, 是 因 為 衍 生 類 別 繼 承 了 其 本 類 別 所 有 的 資 料 與 功 能 3. 但 反 之, 基 本 類 別 不 可 以 作 為 其 衍 生 類 別 來 用 因 基 本 類 別 不 具 備 衍 生 類 別
85 中 所 新 宣 告 定 義 的 資 料 成 員 與 函 式 成 員 ( 如 radius, area) 4. 指 定 給 為 其 基 本 類 別 的 指 標 或 參 考 之 衍 生 類 別 物 件, 如 透 過 基 本 類 別 的 指 標 或 參 考 來 操 作, 其 表 現 出 的 行 為 將 如 同 其 基 本 類 別 一 樣, 而 非 於 衍 生 類 別 中 新 定 義 的 行 為 ( 例 如 print), 也 不 具 新 增 的 功 能 ( 無 法 執 行 area) Note: 與 下 一 章 介 紹 之 Virtual Function 比 較 5. 基 本 類 別 的 指 標, 可 強 制 轉 換 (cast) 成 衍 生 類 別 的 指 標, 使 用 轉 換 後 之 指 標 來 操 作 衍 生 類 別 物 件, 即 回 復 衍 生 類 別 的 行 為 10.1.4 Casting Base-Class Pointers to Derived-Class Pointers 基 本 類 別 之 物 件 並 不 可 視 為 衍 生 類 別 之 物 件, 不 過 程 式 設 計 者 可 明 確 使 用 強 制 轉 換, 將 基 本 類 別 之 指 標 轉 換 成 為 衍 生 類 別 之 指 標, 此 稱 為 downcasting 需 注 意 的 是 要 確 認 指 標 所 指 物 件 的 實 際 型 別 為 何, 雖 可 以 用 downcasting 將 基 本 類 別 之 物 件 指 定 給 衍 生 類 別 之 指 標, 但 存 取 不 存 在 的 成 員 會 造 成 執 行 邏 輯 上 的 錯 誤 程 式 範 例 : oop_ex95.cpp 1. 請 注 意 執 行 的 結 果, 以 circle 指 標 操 作 point 物 件, 由 於 point 物 件 並 沒 有 定 義 radius 等 成 員, 程 式 則 將 radius 預 期 所 在 記 憶 體 位 址 之 現 存 值, 直 接 輸 出 此 有 如 使 用 超 出 陣 列 範 圍 之 索 引 值 對 陣 列 做 存 取 之 情 況 10.2 Protected Member 說 明 : protected 成 員 保 護 程 度 介 於 private 與 public 成 員 之 間, 一 基 本 類 別 的 protected 成 員, 可 被 其 衍 生 類 別 的 成 員 或 朋 友 直 接 存 取, 有 如 public 成 員 但 對 於 其 他 的 類 別, 則 無 法 自 由 存 取, 有 如 private 成 員 於 public 繼 承 的 情 況 下, 衍 生 類 別 對 其 繼 承 而 來 之 成 員 的 存 取 權 限 :
86 (1) public: 所 有 程 式 包 括 其 衍 生 類 別 均 可 直 接 存 取 某 基 本 類 別 的 public 成 員 (2) protected: protected 為 特 別 針 對 繼 承 情 況 的 存 取 設 定, 衍 生 類 別 的 函 式 成 員 與 朋 友 可 直 接 存 取 其 基 本 類 別 的 protected 成 員, 而 其 他 部 分 式 則 不 可 直 接 存 取 某 基 本 類 別 的 protected 成 員 (3) private: 與 所 有 非 基 本 類 別 的 程 式 一 樣, 衍 生 類 別 不 能 直 接 存 取 其 基 本 類 別 的 private 成 員, 衍 生 類 別 對 於 基 本 類 別 的 private 成 員 之 存 取, 需 透 過 基 本 類 別 提 供 宣 告 為 public 或 protected 之 存 取 函 式 (4) 需 注 意 的 是, 朋 友 函 式 並 非 基 本 類 別 之 成 員, 故 無 法 被 繼 承 程 式 範 例 : oop_ex96.cpp 1. 衍 生 類 別 的 建 構 函 式 可 直 接 初 始 化 protected 成 員, 但 一 般 還 是 建 議 使 用 基 本 類 別 的 建 構 函 式 2. 非 衍 生 類 別 之 函 式 成 員, 例 如 主 程 式 內 無 法 存 取 protected 成 員 10.3 public protected and private Inheritance C++ 有 public protected 與 private 三 種 繼 承 方 式, 使 用 protected 與 private 繼 承 是 很 少 見 的 不 同 的 繼 承 方 式 會 影 響 成 員 被 繼 承 後, 於 衍 生 類 別 中 之 權 限 設 定, 其 規 則 如 下 : 基 本 類 別 中 之 成 員 設 定 public 成 員 protected 成 員 private 成 員 public / 可 直 接 存 取 protected / 可 直 接 存 取 繼 承 後 於 衍 生 類 別 之 權 限 設 定 ( 對 外 ) / 衍 生 類 別 函 式 成 員 存 取 方 式 ( 對 內 ) public 繼 承 protected 繼 承 private 繼 承 hidden / 需 透 過 基 本 類 別 提 供 之 存 取 函 式 protected / 可 直 接 存 取 protected / 可 直 接 存 取 hidden / 需 透 過 基 本 類 別 提 供 之 存 取 函 式 private / 可 直 接 存 取 private / 可 直 接 存 取 hidden / 需 透 過 基 本 類 別 提 供 之 存 取 函 式 程 式 範 例 : oop_ex97.cpp oop_ex98.cpp oop_ex99.cpp
87 1. protected 與 private 繼 承 均 不 是 is a 關 係 2. base class 可 分 為 direct base class 與 indirect base class:direct base class 為 宣 告 衍 生 類 別 時, 明 確 以 : 指 定 ;indirect base class 並 非 於 宣 告 衍 生 類 別 時 明 確 指 定, 而 是 衍 生 類 別 時 經 由 二 或 多 層 繼 承, 間 接 由 direct base class 繼 承 來 的 10.4 Copy Constructor and Copy Assignment Operator for Derived Classes 衍 生 類 別 的 拷 貝 建 構 函 式 與 拷 貝 指 定 運 算 子 也 必 須 要 呼 叫 其 基 本 類 別 的 相 對 應 函 式 來 初 始 化 base members, 其 呼 叫 方 式 如 下 : class Employee public: Employee(const Employee& other).. Employee& operator=(const Employee& other)... ; class Manager : public Employee. public: Manager(const Manager& other) : Employee(other) Manager& operator=(const Manager& other) Employee::operator=(other);..
88 程 式 範 例 : oop_ex100.cpp 1. 各 位 可 注 意 到 呼 叫 基 本 類 別 的 拷 貝 建 構 函 式 與 拷 貝 指 定 運 算 子 時, 所 輸 入 參 數 是 衍 生 類 別 的 物 件, 由 於 衍 生 類 別 可 當 作 是 其 基 本 類 別 來 使 用 ( 指 定 給 基 本 類 別 之 指 標 或 參 考 ), 故 此 做 法 並 沒 有 問 題 10.5 Friend Functions in Inheritance 適 用 於 基 本 類 別 的 朋 友 函 式 亦 適 用 於 其 衍 生 類 別 但 其 原 因 並 不 是 衍 生 類 別 繼 承 了 基 本 類 別 的 朋 友 函 式 ( 朋 友 函 式 並 非 一 類 別 的 成 員 ), 而 是 衍 生 類 別 之 物 件 可 當 作 其 基 本 類 別 之 物 件 來 使 用 程 式 範 例 : oop_ex101.cpp 1. 朋 友 函 式 不 能 直 接 存 取 衍 生 類 別 專 有 的 private 成 員 (radius), 故 可 知 其 並 不 是 circle 的 朋 友, 而 只 是 point 的 朋 友 故 可 以 說 一 類 別 的 朋 友 函 式 並 不 具 有 繼 承 的 功 能, 因 為 其 根 本 並 不 是 類 別 的 成 員 之 一 10.6 Relationship between Classes 10.6.1 Composition vs. Inheritance 類 別 間 如 為 public 繼 承, 則 為 is a 之 繼 承 關 係, 即 衍 生 類 別 之 物 件 可 視 為 其 基 本 類 別 之 物 件, 例 如 Manager is a Employee,Car is a Vehicle. 如 類 別 將 其 他 類 別 之 物 件 當 做 成 員, 則 為 has a 之 合 成 關 係, 例 如 Team has a Person,Car has a Engine, 於 合 成 關 係 下, 物 件 可 透 過 彼 此 公 開 之 介 面 交 互 作 用
89 10.6.2 Uses a and Know a Relationship 除 了 繼 承 與 合 成, 類 別 間 還 有 uses a 與 know a 關 係 例 如 Person 與 Car 間 非 繼 承 與 合 成 之 關 係, 但 Person 可 駕 駛 Car, 故 其 間 為 Person uses a Car 之 關 係 物 件 以 指 標 或 參 考 來 參 照 到 其 他 物 件, 稱 為 knows a 關 係, 或 稱 為 association, 表 示 物 件 間 可 透 過 指 標 或 參 考 相 關 聯, 物 件 間 如 為 has a 或 uses a 關 係, 均 可 以 knows a 方 式 相 關 聯 10.7 Multiple Inheritance C++ 之 類 別 可 以 繼 承 自 多 個 基 本 類 別, 這 種 產 生 衍 生 類 別 的 方 式 稱 為 多 重 繼 承 (multiple inheritance), 此 促 成 軟 體 之 重 複 使 用, 但 會 造 成 許 多 混 淆 的 問 題 多 重 繼 承 的 宣 告 格 式 如 下, 繼 承 之 所 有 基 本 類 別 均 指 定 於 : 後, 並 以, 分 開 class Derived : public Base1, public Base2,. 程 式 範 例 : oop_ex102.cpp 1. TA 包 含 了 兩 個 name 資 料 成 員, 一 個 繼 承 自 Staff, 一 個 繼 承 自 Student, 於 TA 中 對 其 存 取 會 有 混 淆 的 情 形 發 生, 需 使 用 範 圍 解 析 運 算 子, 將 其 區 隔 出 來 對 於 沒 有 名 稱 衝 突 者, 如 salary 與 level, 則 可 直 接 存 取 2. 同 樣 的 情 形 也 發 生 於 TA 所 繼 承 之 setdept 與 getdept 函 式 成 員 上 3. is a 關 係, 也 適 用 於 多 重 繼 承, 例 如 TA 之 物 件 可 視 為 Student 之 物 件, 也 可 視 為 Staff 之 物 件 4. 本 範 例 為 簡 單 的 多 重 繼 承,C++ 之 多 重 繼 承 尚 有 其 他 的 問 題, 例 如 diamond hierarchies, 未 來 將 再 做 介 紹