Inheritance Cheng-Chin Chiang
Relationships among Classes A 類 別 使 用 B 類 別 學 生 使 用 手 機 傳 遞 訊 息 公 司 使 用 金 庫 儲 存 重 要 文 件 人 類 使 用 交 通 工 具 旅 行 A 類 別 中 有 B 類 別 汽 車 有 輪 子 三 角 形 有 三 個 頂 點 電 腦 內 有 中 央 處 理 單 元 A 類 別 是 一 種 B 類 別 每 個 正 方 形 是 一 個 矩 形 每 輛 吉 普 車 都 是 一 輛 汽 車 每 匹 白 馬 都 是 匹 馬 C ++ 透 過 類 別 嵌 入 (embedding) 與 類 別 繼 承 (inheritance) 兩 種 方 式 來 處 理 這 三 種 類 別 間 的 關 係
Class Embedding 類 別 嵌 入 將 某 A 類 別 物 件 嵌 入 某 B 類 別 內 甲 類 別 物 件 被 當 成 乙 類 別 內 的 資 料 成 員 class Date { int year, month, day ; }; class Student { private: string name ; bool gender ; Date birthday ; int id ; };
Constructors for Class Embedding 當 A 類 別 內 有 B 類 別 物 件 的 資 料 成 員 時, 則 建 構 每 個 A 類 別 物 件 時, 須 先 行 建 構 B 類 別 物 件 資 料 成 員 class Car { private: Engine engine ; Wheel wheel ; Tire tire ;... };... Car BMW ; // 以 上 BMW 相 當 於 執 行 了 以 下 的 備 用 建 構 函 式 Car::Car() : engine(), wheel(), tire(){}
Destructors for Class Embedding 嵌 入 物 件 消 失 時, 會 依 次 去 除 其 內 資 料 成 員 所 佔 有 的 記 憶 空 間 後, 才 會 真 正 消 失 C++ 是 透 過 執 行 各 成 員 類 別 的 解 構 函 式 來 去 除 資 料 成 員 各 自 佔 用 的 空 間
class A { private: B a ; }; class B { private: C b ; }; class C { };... 建 構 與 解 構 C A obja ; B A
When to Use Class Embedding 擁 有 包 含 // 多 邊 形 包 含 許 多 頂 點 class Polygon { private: Point pts[20] ; }; // 大 學 包 含 許 多 學 院 class University { private: College col[20] ; }; // 顏 色 由 紅, 綠, 藍 三 種 顏 色 組 成 class Color { private: int red, green, blue ; }; 使 用 利 用 class Stack { private: vector<int> data ; // 儲 存 整 數 public: void push( int item ) { data.push_back(item) ; } void pop(){ data.pop_back() ; } int top() const { return data[ data.size()-1 ] ; } }; push 堆 疊 stack 頂 部 底 部 pop top bottom
Introduction to Inheritance 繼 承 : 物 件 導 向 程 式 語 言 的 一 個 好 特 性, 對 應 到 類 別 關 係 中 的 類 別 A 是 類 別 B 車 基 礎 類 別 跑 車 轎 車 貨 車 休 旅 車 衍 生 類 別 Toyota Wish Mazda 5 Ford Escape 實 體 物 件 基 礎 類 別 也 可 稱 為 父 類 別 (parent class) 衍 生 類 別 也 可 稱 為 子 類 別 (child class) 基 本 概 念 先 有 抽 象 基 礎 類 別 (Base Class): 較 為 一 般 化 ( 含 有 共 通 的 屬 性 和 功 能 ) 再 有 具 體 衍 生 類 別 (Derived Class): 較 為 特 殊 化 ( 含 有 各 自 特 別 的 屬 性 和 功 能 ) 衍 生 類 別 可 繼 承 基 礎 類 別 的 屬 性 ( 資 料 成 員 ) 和 功 能 ( 函 數 成 員 ), 也 可 重 新 定 義 功 能 或 是 自 訂 全 新 屬 性 和 功 能
Syntax for Class Inheritance 公 共 繼 承 class Derived : public Base_Class {... } ; 保 護 繼 承 class Derived : protected Base_Class {... } ; 私 有 繼 承 class Derived : private Base_Class {... } ;
Types of Inheritance 衍 生 類 別 的 繼 承 方 式 私 有 區 基 礎 類 別 的 保 護 區 公 共 區 私 有 繼 承 不 繼 承 私 有 區 私 有 區 保 護 繼 承 不 繼 承 保 護 區 保 護 區 公 共 繼 承 不 繼 承 保 護 區 公 共 區 Base Derived 公 共 繼 承 public 公 共 public 公 共
Types of Inheritance (cont.) Base Derived 私 有 繼 承 public 公 共 public 公 共 Base Derived public 公 共 public 公 共 保 護 繼 承
Hierarchical Inheritance A B C public 公 共 public 公 共 public 公 共 class B : public A {...}; class C : public B {...};
Hierarchical Inheritance (cont.) A B C public 公 共 public 公 共 public 公 共 class B : protected A {...} ; class C : public B {...} ; 類 別 C 的 成 員 函 式 仍 可 自 由 地 使 用 在 A 類 別 保 護 區 與 公 共 區 內 的 成 員
Hierarchical Inheritance (cont.) A B C public 公 共 public 公 共 public 公 共 class B : private A {...} ; class C : public B {...} ; 對 C 類 別 而 言, 類 別 A 並 不 存 在, 所 有 類 別 A 的 可 繼 承 成 員 僅 止 於 類 別 B
Single Inheritance vs. Multiple Inheritance class B1 {...} ; class D1 : public B1 {...} ; class D2 : private B1 {...} ; 單 一 繼 承 D1 B1 D2 class B1 {...} ; class B2 {...} ; class D3 : public B1, private B2 {... } ; B1 D3 B2 多 重 繼 承
Single Inheritance vs. Multiple Inheritance: Example 車 子 船 舶 獸 力 車 機 器 動 力 車 馬 車 轎 車 水 陸 兩 用 車 遊 艇
Multiple Inheritance 使 用 多 重 繼 承 時, 若 無 法 明 確 分 辨 所 繼 承 來 的 成 員 函 式 的 來 源, 就 須 將 被 繼 承 類 別 名 稱 一 併 寫 上 class B { public: int abs( int i ){ return i > 0? i : -i ; } }; class C { public: double abs( double d ){ return d > 0? d : -d ; } }; class A : public B, public C {...} ; A foo; cout << foo.b::abs(2) << endl cout << foo.c::abs(2) << endl
Virtual Base Classes C E C C B A D 如 果 C=E B A D A 重 複 繼 承 C, 造 成 資 料 重 複 儲 存 修 正 方 法 : 使 用 虛 擬 基 礎 類 別
Virtual Base Classes C class C {...} ; B D class B : virtual public C {...} ; class D : virtual public C {...} ; A class A : public B, public D {...} ; 此 菱 形 架 構 的 基 礎 類 別 C 被 稱 為 虛 擬 基 礎 類 別 宣 告 為 虛 擬 之 基 礎 類 別 不 管 被 繼 承 幾 次, 只 會 儲 存 一 份 資 料 成 員, 反 之, 非 虛 擬 之 基 礎 類 別 則 會 儲 存 多 份 資 料 成 員 ( 浪 費!)
例 題 : 類 別 繼 承
例 題 : 類 別 繼 承 ( 續 ) 新 增 函 數 重 新 定 義 函 數 不 擬 重 新 定 義 函 數 的 函 數 毋 需 再 列 出!
Files of Derive Classes 衍 生 類 別 的 定 義 檔 (*.h) 須 包 括 : 新 訂 資 料 成 員 與 函 數 成 員 之 宣 告 擬 重 新 定 義 的 成 員 函 數 之 宣 告 衍 生 類 別 的 實 作 檔 (*.cpp) 須 包 括 : 新 成 員 函 數 的 內 部 實 作 重 新 定 義 函 數 的 內 部 實 作
Redefining vs. Overloading 不 同 的 二 件 事 重 新 定 義 函 數 相 同 的 參 數 列 不 同 的 函 數 內 部 設 計 覆 載 ( 多 載 ) 函 數 不 同 的 參 數 列 不 同 的 函 數 內 部 設 計
Accessing Redefined Base Function 即 使 基 礎 類 別 函 數 被 衍 生 類 別 重 新 定 義, 在 衍 生 別 中 依 然 可 以 使 用 基 礎 類 別 之 原 來 函 數 Employee JaneE; HourlyEmployee SallyH; JaneE.printCheck(); // calls Employee s printcheck function SallyH.printCheck(); // calls HourlyEmployee printcheck function SallyH.Employee::printCheck(); // Calls Employee s printcheck function!
Functions Not Inherited 所 有 基 礎 類 別 的 函 數 都 會 被 衍 生 類 別 繼 承, 除 了 建 構 子 Constructors (we ve seen) 結 構 子 Destructors 拷 貝 建 構 子 (Copy constructor) 若 是 沒 有 定 義,compiler 自 動 產 生 一 個 基 本 的 預 設 版 本 ( 可 能 不 是 我 們 真 正 需 要 的 正 確 版 本 ) 最 好 自 己 重 新 設 計, 特 別 是 有 關 動 態 記 憶 體 配 置 的 部 分 指 定 運 算 子 若 是 沒 有 定 義,compiler 自 動 產 生 一 個 基 本 的 預 設 版 本 ( 可 能 不 是 我 們 真 正 需 要 的 正 確 版 本 ) 最 好 自 己 重 新 設 計, 特 別 是 有 關 動 態 記 憶 體 配 置 的 部 分
Derived Class Constructor HourlyEmployee::HourlyEmployee(string thename, string thenumber, double thewagerate, double thehours) : Employee(theName, thenumber), wagerate(thewagerate), hours(thehours) { //Deliberately empty } 記 得 呼 叫 基 礎 類 別 ( 如 Employee) 的 建 構 子, 若 沒 有 明 確 寫 出, 則 基 礎 類 別 的 預 設 建 構 子 會 自 動 被 執 行
Copying and Assignment between Base Classes and Derived Classes 衍 生 類 別 物 件 複 製 / 指 定 到 基 礎 類 別 物 件 class Base {...} ; class Derived : public Base {...} ; Derived foo ; 僅 切 割 衍 生 類 別 所 繼 承 來 的 基 礎 類 別 資 料 成 員 來 複 製 / 指 定 Base bar1(foo) ; Base bar2; bar2 = foo; 基 礎 類 別 物 件 複 製 / 指 定 成 衍 生 類 別 物 件 基 礎 類 別 的 資 料 不 足, 無 法 複 製 / 指 定 成 衍 生 類 別 物 件
Destructors in Derived Classes 當 衍 生 類 別 的 解 構 子 被 呼 叫 時, 基 礎 類 別 的 解 構 子 也 會 自 動 被 呼 叫 因 此, 衍 生 類 別 的 解 構 子 的 設 計 中 只 要 負 責 衍 生 類 別 額 外 新 定 義 的 資 料 成 員 的 收 尾 工 作 即 可
Destructor Calling Order 假 設 class B 繼 承 自 class A class C 繼 承 自 class B 解 構 順 序 :A B C 建 構 子 的 順 序 剛 好 相 反