深 度 學 習 C ++ Chapter 12 類 別 間 的 關 係 ( 一 ) 嵌 入 與 繼 承 1 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 類 別 間 的 關 係 ( 一 ): 使 用 使 用 (use): 某 甲 類 別 使 用 某 乙 類 別 物 件 來 完 成 某 項 事 情 學 生 使 用 手 機 傳 遞 訊 息 公 司 使 用 金 庫 儲 存 重 要 文 件 人 類 使 用 交 通 工 具 旅 行 2 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 1
類 別 間 的 關 係 ( 二 ): 有 一 個 有 一 個 (has a): 某 乙 類 別 物 件 被 置 入 某 甲 類 別 內 當 成 必 要 的 一 部 分 使 用 汽 車 有 輪 子 三 角 形 有 三 個 頂 點 昆 蟲 有 六 隻 腳 計 算 機 內 有 中 央 處 理 單 元 3 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 類 別 間 的 關 係 ( 三 ): 是 一 個 是 一 個 (is a): 某 甲 類 別 物 件 也 可 以 被 當 成 某 乙 類 別 物 件 使 用 每 個 正 方 形 是 一 個 矩 形, 矩 形 的 內 角 皆 是 直 角 因 此 正 方 形 的 內 角 也 是 直 角 每 輛 吉 普 車 都 是 一 輛 汽 車, 若 汽 車 可 以 用 來 載 貨 代 步 則 吉 普 車 同 樣 也 可 以 每 匹 白 馬 都 是 馬, 馬 可 以 用 來 載 人 代 步 馱 物 則 白 馬 當 然 也 可 以 4 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 2
使 用, 有 一 個, 是 一 個 ( 一 ) 隨 著 問 題 的 不 同, 類 別 間 的 關 係 也 不 是 僅 有 一 種, 且 保 持 不 變 若 有 以 下 九 種 類 別 : 書 籍 歷 史 書 兒 童 書 小 說 書 名 作 者 價 格 書 局 封 套 則 每 一 本 書 籍 都 有 書 名 作 者 價 格 has 有 歷 史 書 兒 童 書 小 說 都 是 一 本 書 is 是 每 間 書 局 都 有 許 多 書 每 一 本 書 籍 可 以 使 用 封 套 來 保 護 書 籍 has 有 uses 使 用 5 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 使 用, 有 一 個, 是 一 個 ( 二 ) 若 有 以 下 幾 種 類 別 : 主 機 零 件 中 央 處 理 單 元 硬 碟 機 殼 光 碟 機 記 憶 體 鍵 盤 滑 鼠 風 扇 鍵 盤 列 表 機 喇 叭 螢 幕 鍵 盤 價 格 存 貨 數 量 則 每 種 零 組 件 都 有 價 格 與 存 貨 數 量 has 有 硬 碟 機 殼 記 憶 體 等 都 是 電 腦 零 件 is 是 每 個 主 機 都 有 硬 碟 CPU RAM has 有 主 機 用 喇 叭 發 出 聲 音, 螢 幕 顯 示 畫 面 uses 使 用 C ++ 透 過 類 別 嵌 入 與 類 別 繼 承 兩 種 方 式 來 處 理 這 三 種 類 別 間 的 關 係 6 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 3
類 別 嵌 入 ( 一 ) 類 別 嵌 入 (class embedding) : 將 某 甲 類 別 物 件 埋 入 某 乙 類 別 內, 相 當 於 甲 類 別 物 件 被 當 成 乙 類 別 內 的 資 料 成 員 擁 有 : 乙 類 別 內 擁 有 著 甲 類 別 物 件 資 料 成 員, 則 每 個 乙 類 別 物 件 就 帶 有 著 甲 類 別 的 特 徵 7 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 類 別 嵌 入 ( 二 ) 每 個 學 生 都 有 姓 名 性 別 出 生 年 月 日 學 號 等 資 料 // 列 舉 資 料 型 別 : 性 別 enum gender { female, male } ; // 結 構 資 料 型 別 : 日 期 struct Date { int year, month, day ; class Student { private: string name ; // 姓 名 gender gedr ; // 性 別 Date birthday ; // 出 生 時 間 int id ; // 學 號 8 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 4
類 別 嵌 入 : 建 構 函 式 設 定 ( 一 ) 當 甲 類 別 內 有 著 乙 類 別 物 件 的 資 料 成 員 時, 則 每 個 甲 類 別 物 件 產 生 之 際, 乙 類 別 物 件 資 料 成 員 須 先 行 建 構 完 成 如 同 一 輛 車 子 內 有 引 擎 方 向 盤 等 零 組 件, 當 汽 車 要 出 廠 使 用 之 前, 引 擎 方 向 盤 等 零 組 件 一 定 要 先 建 構 完 成 且 安 裝 到 車 子 內 一 樣 9 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 類 別 嵌 入 : 建 構 函 式 設 定 ( 二 ) class Car{ private: Engine engine ; Wheel wheel ; Tire tire ;...... Car BMW ; // 引 擎 資 料 成 員 // 方 向 盤 資 料 成 員 // 輪 子 資 料 成 員 以 上 BMW 相 當 於 執 行 了 以 下 的 備 用 建 構 函 式 Car::Car() : engine(), wheel(), tire(){} 類 別 內 資 料 成 員 建 構 次 序 是 依 資 料 成 員 在 類 別 內 宣 告 的 次 序 一 致, 與 起 始 設 定 列 的 次 序 無 關 10 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 5
類 別 嵌 入 : 解 構 函 式 嵌 入 物 件 消 失 時, 會 依 次 去 除 其 內 資 料 成 員 所 佔 有 的 記 憶 空 間 後, 才 會 真 正 消 失 內 部 資 料 成 員 佔 有 空 間 的 去 除 是 透 過 執 行 各 成 員 類 別 的 解 構 函 式 來 達 成 各 內 部 資 料 成 員 解 構 函 式 執 行 的 順 序 剛 好 與 建 構 函 式 執 行 的 順 序 相 反, 也 就 是 先 產 生 的 資 料 成 員, 後 被 移 除 11 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 建 構 與 解 構 的 執 行 步 驟 class A { private: B p ; class B { private: C q ; class C {... A foo ; C B A 12 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 6
類 別 嵌 入 的 使 用 時 機 ( 一 ) 擁 有, 包 含 : 多 邊 形 包 含 許 多 頂 點 class Polygon{ private: Point pts[20] ; 顏 色 由 紅, 綠, 藍 三 種 顏 色 組 成 class Color{ private: int red, green, blue ; 大 學 包 含 許 多 學 院 class University{ private: College col[20] ; 13 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 類 別 嵌 入 的 使 用 時 機 ( 二 ) 使 用, 利 用 : 某 甲 類 別 利 用 嵌 入 的 乙 類 別 物 件 的 某 些 功 能 來 完 成 某 些 事 情 14 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 7
類 別 嵌 入 的 使 用 時 機 ( 三 ) 向 量 陣 列 : 可 調 式 陣 列 // 定 義 一 個 零 長 度 的 向 量 陣 列 vector<int> foo ; // 存 入 6 個 整 數 5 for(int i=0 ; i<6 ; ++i) foo.push_back(5); // 印 出 所 有 向 量 陣 列 的 元 素 值 :555555 for(int i=0 ; i<foo.size() ; ++i) cout << foo[i] << ; // 六 個 元 素 移 除 末 尾 兩 個 元 素 後, 印 出 陣 列 長 度 :4 foo.pop_back(); foo.pop_back(); cout << foo.size() << endl ; 陣 列 複 製 vector<int> foo, bar ;... bar = foo ; // 將 foo 向 量 陣 列 複 製 給 bar 向 量 陣 列 15 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 類 別 嵌 入 的 使 用 時 機 ( 四 ) 堆 疊 類 別 : push pop 旋 轉 90 度 頂 部 top 堆 疊 stack 程 式 碼 : class Stack{ private: vector<int> data ; public: 底 部 bottom // 儲 存 整 數 void push( int item ){ data.push_back(item) ; } void pop(){ data.pop_back(); } int top() const { return data[ data.size()-1 ] ; } 16 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 8
簡 易 選 課 程 式 某 補 習 班 開 設 一 門 課 程 const int MAX_CLASS = 3 ; const int MAX_STUDENT = 10 ; 主 要 類 別 課 程 (Course), 班 別 (Class), 學 生 (Student) 類 別 關 係 每 一 個 課 程 包 含 若 干 個 班 別 每 一 個 班 別 包 含 若 干 個 學 生 程 式 碼 連 結 輸 出 17 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 唐 詩 三 百 首 資 料 庫 設 計 程 式 儲 存 不 限 定 數 量 的 五 言 詩 與 七 言 詩 主 要 類 別 詩 (Poem), 唐 詩 資 料 庫 (Tang_Poem) 類 別 關 係 唐 詩 資 料 庫 內 儲 存 兩 種 類 型 的 唐 詩 vector<poem> five ; vector<poem> seven ; 程 式 碼 連 結 輸 出 18 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 9
類 別 間 的 繼 承 關 係 三 種 繼 承 方 式 與 語 法 公 共 繼 承 (public inheritance) class Derived : public Base{... 保 護 繼 承 (protected inheritance) class Derived : protected Base{... 私 有 繼 承 (private inheritance) class Derived : private Base{... 19 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 基 礎 類 別 與 衍 生 類 別 基 礎 類 別 (base class) 被 繼 承 的 類 別 衍 生 類 別 (derived class, subclass) 繼 承 的 類 別 公 共 繼 承 非 公 共 繼 承 基 礎 類 別 Base class 被 繼 承 類 別 基 礎 類 別 Base class 衍 生 類 別 Derived class 繼 承 類 別 衍 生 類 別 Derived class 基 礎 類 別 也 可 稱 為 父 類 別 ( parent class ) 衍 生 類 別 也 可 稱 為 子 類 別 ( child class ) 20 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 10
多 重 繼 承 一 個 基 礎 類 別 可 有 若 干 個 衍 生 類 別 class B1 {...} ; class D1 : public B1 {...} ; class D2 : private B1 {...} ; 一 個 衍 生 類 別 也 可 有 若 干 個 基 礎 類 別 class B2 {...} ; class D3 : public B1, private B2 {...} ; 此 種 繼 承 方 式 被 稱 為 多 重 繼 承 (multiple inheritance) 21 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 類 別 架 構 若 干 個 類 別 繼 承 關 係 可 聯 結 在 一 起 成 為 類 別 架 構 (class hierarchy) 車 子 船 舶 獸 力 車 機 器 動 力 車 馬 車 轎 車 水 陸 兩 用 車 遊 艇 22 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 11
最 常 見 的 繼 承 關 係 公 共 繼 承 是 三 種 繼 承 方 式 中 最 常 用 的 繼 承 模 式 // 基 礎 類 別 class Base {...} ; // 衍 生 類 別 : 公 共 繼 承 方 式 class Derived : public Base {...} ; 其 他 兩 種 類 型 在 實 際 應 用 上 較 少 出 現 23 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 三 種 類 別 資 料 存 取 區 域 ( 一 ) 類 別 內 的 資 料 與 函 式 都 須 置 放 在 以 下 三 種 存 取 區 域 之 一 : 公 共 存 取 區 保 護 存 取 區 私 有 存 取 區 三 種 存 取 區 域 的 差 別 資 料 成 員 與 成 員 函 式 使 用 方 式 可 為 類 別 內 的 所 有 成 員 函 式 使 用 可 為 衍 生 類 別 所 有 成 員 函 式 使 用 可 為 類 別 的 物 件 所 使 用 私 有 存 取 區 o x x 私 有 存 取 區 o o x 私 有 存 有 區 o o o 24 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 12
三 種 類 別 資 料 存 取 區 域 ( 二 ) 程 式 範 例 class Base{ private: int a(); protected: int b(); public: int c1(); int c2(); int c3();... Base foo ; foo.a() ; foo.b() ; foo.c1() ; // 錯 誤, a() 為 私 有 區 域 內 的 成 員 函 式, 不 得 直 接 使 用 // 錯 誤, b() 為 保 護 區 域 內 的 成 員 函 式, 不 得 直 接 使 用 // 正 確 25 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 三 種 類 別 資 料 存 取 區 域 ( 三 ) class Derived : public Base{ private: int d1(){ return a(); } // 錯 誤,Base::a() 為 Base 類 別 的 // 私 有 成 員 函 式 不 能 被 衍 生 類 別 所 使 用 int d2(){ return b(); } int d3(){ return c1(); } int c1(){ return Base::c2(); } int c2(){... return c2(); } public: int d4(){ return b(); } int d5(){ return c3(); } // 正 確 // 正 確 // 正 確 // 正 確 // 使 用 Base::c2() // 遞 迴 使 用 //Derived::c2() 衍 生 類 別 的 成 員 函 式 所 能 使 用 到 的 基 礎 類 別 成 員 與 繼 承 方 式 無 關 26 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 13
多 重 繼 承 ( 一 ) 多 重 繼 承 (multiple inheritance) 衍 生 類 別 繼 承 了 兩 個 以 上 的 基 礎 類 別 B C A class B {...} ; class C {...} ; class A : public B, public C {...} ; 27 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 多 重 繼 承 ( 二 ) 使 用 多 重 繼 承 時, 若 無 法 分 辨 所 要 使 用 的 成 員 函 式 的 來 源, 就 須 將 類 別 名 稱 一 併 寫 上 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.abs(2) << endl; cout << foo.a::abs(2) << endl; // 須 註 明 所 要 使 用 的 abs 來 源 // 2 可 以 自 動 轉 型 成 浮 點 數 2 編 譯 // 器 無 法 分 辨 是 foo.b::abs(2) 或 // foo.c::abs(2) 28 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 14
虛 擬 基 礎 類 別 ( 一 ) 若 有 一 多 層 次 的 多 重 繼 承 為 class C {...} ; C E class E {...} ; B D A class B : public C {...} ; class D : public E {...} ; class A : public B, public D {...} ; 以 上 若 類 別 C 與 類 別 E 相 同 時 則 以 上 的 定 義 方 式 會 被 解 讀 為 C C class C {...} ; class B : public C {...} ; B D class D : public C {...} ; A class A : public B, public D {...} ; 29 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 虛 擬 基 礎 類 別 ( 二 ) 之 前 的 定 義 造 成 類 別 C 重 複 繼 承, 資 料 重 複 儲 存 可 以 用 以 下 方 式 加 以 調 整 B C class C {...} ; class B : virtual public C {...} ; D A class D : virtual public C {...} ; class A : public B, public D {...} ; 此 菱 形 架 構 的 基 礎 類 別 C 被 稱 為 虛 擬 基 礎 類 別 ( virtual base class ) 30 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 15
繼 承 與 遺 傳 不 同 的 繼 承 方 式 代 表 著 不 同 型 式 的 遺 傳 衍 生 類 別 的 繼 承 方 式 私 有 區 基 礎 類 別 保 護 區 公 共 區 私 有 繼 承 不 繼 承 私 有 區 私 有 區 保 護 繼 承 不 繼 承 保 護 區 保 護 區 公 共 繼 承 不 繼 承 保 護 區 公 共 區 不 同 的 繼 承 方 式 代 表 著 不 同 的 使 用 義 涵 31 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 公 共 繼 承 ( 一 ) 資 料 繼 承 模 式 Base Derived private 私 有 private 私 有 protected 保 護 protected 保 護 public 公 共 public 公 共 class Derived : public Base {... 義 涵 : 是 一 個 ( is a ) 對 基 礎 類 別 而 言, 基 礎 類 別 物 件 與 衍 生 類 別 物 件 有 著 同 樣 的 使 用 權 限 基 礎 類 別 物 件 所 能 執 行 的 成 員 函 式, 每 個 衍 生 類 別 物 件 也 能 執 行 每 個 衍 生 類 別 物 件 可 視 為 一 個 基 礎 類 別 物 件 32 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 16
公 共 繼 承 ( 二 ) 是 一 個 公 共 繼 承 吉 普 車 車 子 卡 車 class Car {... class Jeep : public Car {... class Truck : public Car {... 車 輛 類 別 架 構 Car Jeep Truck 33 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 公 共 繼 承 ( 三 ) 在 公 共 繼 承 下 的 類 別 架 構 基 礎 類 別 : 為 所 有 衍 生 類 別 的 共 同 交 集 衍 生 類 別 : 為 與 其 它 衍 生 類 別 間 的 個 別 差 異 34 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 17
公 共 繼 承 書 商 範 例 ( 一 ) 相 關 類 別 Book, History_Book, Kid_Book, Novel, Book_name, Auther, Price, Bookstore 類 別 關 係 每 一 本 書 籍 都 有 書 名 作 者 價 格 has 有 書 局 都 有 許 多 書 has 有 歷 史 書 兒 童 書 小 說 都 是 一 本 書 is 是 35 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 公 共 繼 承 書 商 範 例 ( 二 ) 每 本 書 都 有 書 名, 作 者, 價 格 class Book { private: Book_Name bookname ; Author author ; Price price ; 書 店 裡 都 有 許 多 本 書 const int MAX = 1000 ; class Bookstore { private: Book book[max]; // 書 名 // 作 者 // 價 格 // 1000 本 書 36 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 18
公 共 繼 承 書 商 範 例 ( 三 ) 每 一 本 歷 史 書 兒 童 書 小 說 都 是 一 本 書 class Hitory_Book : public Book {... class Kid_book : public Book {... class Novel : public Book {... // 歷 史 書 是 書 // 兒 童 書 是 書 // 小 說 是 書 書 有 衍 生 類 別 class Book { protected: Book_Name bookname ; Auther auther ; Price price ; // 書 名 // 作 者 // 價 格 37 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 公 共 繼 承 : 是 一 個 在 公 共 繼 承 下, 每 個 衍 生 類 別 物 件 可 視 為 一 個 基 礎 類 別 物 件 詩, 五 言 詩 class Poem {... class Five_Short_Poem : public Poem {... 列 印 詩 的 內 容 void print_poem( const Poem& P ){... 則 Poem foo ; print_poem( foo ) ; Five_Short_Poem bar ; print_poem( bar ) ; 38 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 19
公 共 繼 承 : 多 層 繼 承 ( 一 ) A, B, C 三 類 別 為 class A { protected: int abs( int x ){ return x > 0? x : -x ; } public: int square( int x ){ return x * x ; } class B : public A { public: int cubic( int x ){ return x * square(x) ; } class C : public B { public: int abs_sum( int x, int y ){ return abs(x) + abs(y) ; } int square_sum( int x, int y ){ return square(x) + square(y) ; } int cubic_sum( int x, int y ){ return cubic(x) + cubic(y) ; } 39 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 公 共 繼 承 : 多 層 繼 承 ( 二 ) 使 用 方 式 C foo; cout << foo.abs(-3) << endl; // 錯 誤, A::abs 函 式 並 不 能 為 類 別 物 件 所 使 用 cout << foo.square(3) cout << foo.cubic(3) cout << foo.abs_sum(-3,4) << endl; << endl; << endl; cout << foo.square_sum(3,4) << endl; cout << foo.cubic(10,1) << endl; // 印 出 : 9 // 印 出 : 27 // 印 出 : 1 // 印 出 : 25 // 印 出 : 1001 40 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 20
公 共 繼 承 : 多 層 繼 承 ( 三 ) 若 有 一 類 別 架 構 A B C private 私 有 private 私 有 private 私 有 protected 保 護 protected 保 護 protected 保 護 public 公 共 public 公 共 public 公 共 class B : public A {... class C : public B {... 41 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 保 護 繼 承 ( 一 ) 資 料 繼 承 模 式 Base Derived private 私 有 private 私 有 protected 保 護 protected 保 護 public 公 共 public 公 共 class Derived : protected Base {... 義 涵 : 使 用 ( use ) 衍 生 類 別 的 成 員 函 式 可 以 自 由 地 使 用 定 義 在 基 礎 類 別 保 護 區 與 公 共 區 內 的 成 員, 可 避 免 程 式 碼 的 重 複 撰 寫 以 衍 生 類 別 物 件 的 觀 點 來 看, 基 礎 類 別 並 不 存 在 42 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 21
保 護 繼 承 ( 二 ) 基 礎 類 別 與 衍 生 類 別 無 因 果 邏 輯 間 的 關 係 class Wind {... class Horse : protected Wind {... class Cow : protected Wind {... 43 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 保 護 繼 承 : 多 層 繼 承 ( 一 ) 若 有 一 類 別 架 構 A B C private 私 有 private 私 有 private 私 有 protected 保 護 protected 保 護 protected 保 護 public 公 共 public 公 共 public 公 共 class B : protected A {...} ; class C : public B {...} ; C 類 別 的 成 員 函 式 仍 可 自 由 地 使 用 在 A 類 別 保 護 區 與 公 共 區 內 的 成 員 函 式 44 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 22
保 護 繼 承 : 多 層 繼 承 ( 二 ) A, B, C 三 類 別 為 class A { public: int square( int x ){ return x * x ; } class B : protected A { public: int cubic( int x ){ return x * square(x) ; } class C : public B { public: int square_sum( int x, int y ){ return square(x) + square(y) ; } int cubic_sum( int x, int y ){ return cubic(x) + cubic(y) ; } 45 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 保 護 繼 承 : 多 層 繼 承 ( 三 ) 使 用 方 式 C foo; cout << foo.square(3) << endl; // 錯 誤, C 類 別 的 公 共 區 內 無 square 函 式 cout << foo.cubic(3) << endl; cout << foo.square_sum(3,4) << endl; cout << foo.cubic(10,1) << endl; // 印 出 : 27 // 印 出 : 25 // 印 出 : 1001 46 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 23
私 有 繼 承 ( 一 ) 資 料 繼 承 模 式 Base Derived private 私 有 private 私 有 protected 保 護 protected 保 護 public 公 共 public 公 共 class Derived : private Base {... 47 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 私 有 繼 承 ( 二 ) 義 涵 : 利 用 衍 生 類 別 所 繼 承 來 的 基 礎 類 別 資 料 僅 能 為 其 內 的 函 式 使 用 以 衍 生 類 別 物 件 的 觀 點 來 看, 基 礎 類 別 並 不 存 在 基 礎 類 別 與 衍 生 類 別 之 間 不 須 有 邏 輯 關 係 存 在 48 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 24
私 有 繼 承 : 多 層 繼 承 ( 一 ) 若 有 一 類 別 架 構 A B C private 私 有 private 私 有 private 私 有 protected 保 護 protected 保 護 protected 保 護 public 公 共 public 公 共 public 公 共 class B : private A {...} ; class C : public B {...} ; 對 C 類 別 而 言, 類 別 A 並 不 存 在, 所 有 類 別 A 的 可 繼 承 成 員 僅 止 於 類 別 B 49 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 私 有 繼 承 : 多 層 繼 承 ( 二 ) A, B, C 三 類 別 為 class A { public: int square( int x ){ return x * x ; } class B : private A { public: int cubic( int x ){ return x * square(x) ; } class C : public B { public: // 錯 誤, C 類 別 無 法 取 用 A 類 別 的 square 函 式 int square_sum( int x, int y ){ return square(x) + square(y) ; } int cubic_sum( int x, int y ){ return cubic(x) + cubic(y) ; } 50 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 25
私 有 繼 承 : 多 層 繼 承 ( 三 ) 使 用 方 式 C foo; cout << foo.square(-3) << endl; // 錯 誤, C 類 別 的 公 共 區 內 並 無 square 函 式 cout << foo.cubic(3) << endl; cout << foo.cubic_sum(10,1) << endl; // 印 出 : 27 // 印 出 : 1001 不 管 是 使 用 保 護 或 私 有 繼 承, 衍 生 類 別 物 件 都 不 能 使 用 在 基 礎 類 別 公 共 區 的 成 員 51 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 衍 生 類 別 物 件 的 建 構 ( 一 ) 衍 生 類 別 物 件 的 建 構 衍 生 類 別 是 建 立 在 基 礎 類 別 的 基 礎 之 下, 因 此 基 礎 類 別 的 資 料 須 在 衍 生 類 別 資 料 建 立 之 前 完 成 建 構 策 略 利 用 衍 生 類 別 建 構 函 式 中 的 初 值 設 定 列 來 設 定 直 屬 基 礎 類 別 的 資 料 52 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 26
衍 生 類 別 物 件 的 建 構 ( 二 ) 若 一 類 別 架 構 為 A B C D 個 別 建 構 函 式 執 行 與 完 成 的 順 序 建 構 E 物 件 E -> C -> A -> C -> E 建 構 F 物 件 F -> D -> A -> D -> F E F G H 53 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 衍 生 類 別 物 件 的 建 構 ( 三 ) 類 別 若 有 兩 個 以 上 的 基 礎 類 別 則 基 礎 類 別 資 料 建 構 的 順 序 與 繼 承 次 序 一 致 的 A B C D 若 是 建 構 G 物 件 E F G H class G : public D, public B {... G -> D -> A -> D -> B -> G class G : public B, public D {... G -> B -> D -> A -> D -> G 54 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 27
衍 生 類 別 物 件 的 建 構 ( 四 ) 若 有 FOO, BAR, FBAR 三 類 別 FOO class FOO{ public : FOO() {... } // 1 FOO( int i ) {... } // 2 } ; class BAR : public FOO { BAR public : BAR( int i = 0 ) {... } // 3 BAR( int i, int j ) : FOO(i) {... } // 4 } ; FBAR class FBAR : public BAR{ public : FBAR() {... } // 5 FBAR( int i ) : BAR(i) {... } // 6 FBAR( int i, int j ) : BAR(i,j) {...} // 7 } ; 55 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 衍 生 類 別 物 件 的 建 構 ( 五 ) 物 件 建 構 FBAR a ; FBAR b(2) ; FBAR c(1,2) ; // 遞 迴 執 行 建 構 函 式 5 -> 3 -> 1 -> 3 -> 5 // 遞 迴 執 行 建 構 函 式 6 -> 3 -> 1 -> 3 -> 6 // 遞 迴 執 行 建 構 函 式 7 -> 4 -> 2 -> 4 -> 7 在 衍 生 類 別 建 構 函 式 的 初 始 設 定 列 中, 僅 須 執 行 直 屬 的 基 礎 類 別 建 構 函 式 即 可, 不 須 設 定 在 其 上 的 所 有 基 礎 類 別 class FBAR : public BAR { public : FBAR( int i ) : BAR(i), FOO(i) {...} // 錯 誤 56 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 28
衍 生 類 別 物 件 的 消 失 ( 一 ) 衍 生 類 別 物 件 的 解 構 順 序 與 建 構 的 完 成 順 序 剛 好 相 反 解 構 步 驟 : 由 衍 生 類 別 解 構 函 式 起 往 上 依 次 執 行 基 礎 類 別 的 解 構 函 式 直 到 最 頂 層 為 止 57 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 衍 生 類 別 物 件 的 消 失 ( 二 ) A 3 class C : public B, public D {...} ; 3 A D 4 B 2 2 B 1 C C 1 class C : public D, public B {...} ; A 4 2 D 3 B C 1 58 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 29
類 別 物 件 的 複 製 與 指 定 ( 一 ) 類 別 架 構 下 的 同 類 別 物 件 複 製 : 利 用 各 類 別 的 複 製 建 構 函 式 完 成 複 製, 複 製 的 執 行 步 驟 與 之 前 的 物 件 產 生 所 執 行 的 方 式 相 同 類 別 架 構 下 的 類 別 類 別 若 未 使 用 到 動 態 空 間 成 員, 則 可 以 省 略 不 寫,C ++ 會 自 行 產 生, 但 若 某 類 別 內 有 使 用 到 動 態 空 間 成 員, 則 仍 要 針 對 此 類 別 自 行 撰 寫 其 複 製 建 構 函 式 資 料 的 指 定 動 作 與 複 製 程 序 相 同 59 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 類 別 物 件 的 複 製 與 指 定 ( 二 ) 衍 生 類 別 物 件 複 製 到 基 礎 類 別 物 件 class Base {...} ; class Derived : public Base {...} ; Derived foo ; Base bar(foo) ; 採 用 切 割 (slicing) 方 式 複 製, 即 僅 複 製 衍 生 類 別 所 繼 承 來 的 基 礎 類 別 資 料 成 員 基 礎 類 別 物 件 複 製 成 衍 生 類 別 物 件 : 資 料 不 足 無 法 複 製 60 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 30
類 別 物 件 的 複 製 與 指 定 ( 三 ) 衍 生 類 別 物 件 指 定 給 基 礎 類 別 物 件 class Base {...} ; class Derived : public Base {...} ; Derived foo ; Base bar ; bar = foo ; 也 是 採 用 切 割 方 式 指 定 基 礎 類 別 物 件 指 定 給 衍 生 類 別 物 件 Derived foo ; Base bar ; foo = bar ; bar = foo 與 bar = static_cast<base>(foo) 相 同 // 錯 誤, 資 料 不 足 61 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 衍 生 類 別 物 件 的 執 行 效 率 在 類 別 架 構 下, 建 構 一 個 越 底 層 的 衍 生 類 別 物 件 執 行 時 間 越 久 class A {...} ; B A class B {...} ; class C : public B {...} ; C class D : public A, public C {...} ;... D for ( int i = 0 ; i < 100 ; ++i ) { D foo ;... } 增 進 效 率 方 式 : 經 常 使 用 的 衍 生 類 別 在 設 計 上 儘 量 放 置 於 類 別 架 構 上 層 在 底 層 的 衍 生 類 別 物 件 儘 量 避 免 經 常 性 的 產 生 與 消 失 62 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 31
衍 生 類 別 與 基 礎 類 別 的 成 員 函 式 避 免 在 衍 生 類 別 內 定 義 與 基 礎 類 別 同 樣 的 成 員 函 式 在 公 共 繼 承 下 的 類 別 關 係, 每 個 衍 生 類 別 物 件 可 視 同 一 個 基 礎 類 別 物 件, 若 執 行 基 礎 類 別 的 公 共 成 員 函 式 應 產 生 相 同 的 結 果, 因 此 無 必 要 在 衍 生 類 別 內 重 複 定 義 相 同 特 徵 資 料 的 成 員 函 式 A B 63 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 點 多 邊 形 三 角 形 ( 一 ) 類 別 關 係 每 一 多 邊 形 三 角 形 都 包 含 若 干 個 點 每 一 個 三 角 形 是 一 個 多 邊 形 嵌 入 公 共 繼 承 struct Point { double x, y ; Point( double a, double b ) : x(a), y(b){} } ; class Polygon { protected : vector<point> vertex ; public : int vertex_no() const { return vertex.size() ; } Point geometrical_center() const {... } } ; class Triangle : public Polygon { public : Triangle() {} Triangle( Point pt1, Point pt2, Point pt3 ){ vertex.push_back( pt1 ) ; vertex.push_back( pt2 ) ; vertex.push_back( pt3 ) ; } Point circumcerter() const {...} } ; 64 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 32
點 多 邊 形 三 角 形 ( 二 ) 避 免 在 三 角 形 類 別 定 義 以 下 函 式 int Triangle::vertex_no() const { return 3 ; } 在 公 共 繼 承 的 類 別 架 構 下, 基 礎 類 別 是 所 有 衍 生 類 別 的 交 集, 而 個 別 的 衍 生 類 別 內 定 義 的 成 員 函 式 則 是 衍 生 類 別 間 的 個 別 差 異 65 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 靜 態 型 別 與 動 態 型 別 ( 一 ) 相 同 的 成 員 函 式 介 面, 不 同 的 實 作 程 式 string Polygon::name() const { return 多 邊 形 ; } string Triangle::name() const { return 三 角 形 ; } 若 定 義 函 式 void print_vertex_no( const Polygon& p ) { cout << p.name() << : << p.vertex.no() ; } 66 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 33
靜 態 型 別 與 動 態 型 別 ( 二 ) 多 邊 形 物 件 Polygon foo ; // 產 生 一 多 邊 形 物 件... print_vertex_no( foo ) ; // 列 印 多 邊 形 名 稱 與 頂 點 數 三 角 形 物 件 Triangle bar ; // 產 生 一 三 角 形 物 件... print_vertex_no( bar ) ; // 列 印 三 角 形 名 稱 與 頂 點 數 67 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 靜 態 型 別 與 動 態 型 別 ( 三 ) 之 前 的 函 式 參 數 設 定 中,C ++ 執 行 了 // 這 裡 bar 是 Triangle 物 件,p 是 bar 的 參 考 const Polygon& p = bar ; 以 上 等 號 的 左 右 兩 邊 型 別 不 同 靜 態 型 別 (static type): 等 號 左 邊 的 型 別, 在 宣 告 時 原 有 的 固 定 型 別, 即 Polygon 動 態 型 別 (dynamic type): 等 號 右 邊 的 型 別, 在 執 行 時 真 正 參 考 的 型 別, 即 Triangle 靜 態 型 別 在 編 譯 時 就 可 確 定 動 態 型 別 在 執 行 時 才 能 確 定 68 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 34
靜 態 型 別 與 動 態 型 別 ( 四 ) 雙 型 別 型 式 的 物 件 也 可 能 出 現 在 指 標 型 物 件 // ptr 的 靜 態 型 別 為 Plolygon, 動 態 型 別 與 bar 型 別 相 同 Polygon *ptr = &bar ; 沒 有 使 用 參 考 或 指 標 類 型 的 物 件 則 沒 有 所 謂 的 動 態 型 別 69 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 虛 擬 函 式 ( 一 ) 類 別 架 構 內 的 函 式 區 分 為 兩 大 類 型 虛 擬 函 式 : 成 員 函 式 之 前 有 virtual 保 留 字 非 虛 擬 函 式 : 成 員 函 式 之 前 無 virtual 保 留 字 class Polygon {... public : virtual string name() const { return 多 邊 形 ; } } ; class Triangle {... public : virtual string name() const { return 三 角 形 ; } } ; 70 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 35
虛 擬 函 式 ( 二 ) 虛 擬 函 式 為 動 態 設 定 (dynamically bound) 函 式 物 件 執 行 虛 擬 函 式 時, 其 所 真 正 執 行 的 成 員 函 式 是 定 義 在 物 件 的 動 態 型 別 內 非 虛 擬 函 式 為 靜 態 設 定 (statically bound) 函 式 物 件 執 行 非 虛 擬 函 式 時, 其 所 真 正 執 行 的 成 員 函 式 為 物 件 的 靜 態 型 別 71 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 虛 擬 函 式 ( 三 ) 多 邊 形 類 別 class Polygon {... public : virtual string name() const { return 多 邊 形 ; } } ; 則 在 void print_vertex_no( const Polygon& p ) { cout << p.name() << : << p.vertex_no() ; } 中 的 p.name() 執 行 p 的 動 態 型 別 內 的 name() p.vertex_no() 執 行 p 的 靜 態 型 別 內 的 vertex_no() 若 動 態 型 別 內 並 無 定 義 對 應 的 虛 擬 函 式 則 C ++ 會 執 行 在 靜 態 型 別 的 函 式 72 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 36
虛 擬 函 式 的 涵 義 ( 一 ) 虛 擬 函 式 : 動 態 型 別 的 對 應 函 式 由 於 動 態 型 別 須 留 待 執 行 時 才 能 確 定, 因 此 真 正 執 行 的 程 式 碼 隨 之 不 同 相 同 的 使 用 介 面 不 同 的 執 行 實 體 虛 擬 函 式 代 表 多 型 (polymorphic function) 73 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 虛 擬 函 式 的 涵 義 ( 二 ) 多 型 函 式 : 在 程 式 正 式 執 行 後 才 能 決 定 函 式 介 面 所 對 應 的 程 式 實 體 int kind ; cout << 輸 入 所 要 使 用 的 物 件 :1 為 Polygon, 2 為 Triangle ; cin >> kind ; // 若 是 1 則 動 態 產 生 Polygon 物 件, 2 為 Triangle 物 件 // 再 由 Polygon 指 標 ptr 指 向 此 新 產 生 的 物 件 Polygon *ptr = ( kind == 1? new Polygon : new Triangle ) ; 74 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 37
虛 擬 函 式 的 涵 義 ( 三 ) 虛 擬 函 式 相 同 的 使 用 介 面 不 同 的 執 行 實 體 非 虛 擬 函 式 相 同 的 使 用 介 面 固 定 的 執 行 實 體 75 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 各 種 成 員 函 式 的 使 用 時 機 ( 一 ) 虛 擬 函 式 : 若 某 函 式 為 類 別 架 構 內 所 有 類 別 共 同 擁 有 的 功 能 或 特 徵, 且 會 因 類 別 的 不 同 而 運 算 方 式 有 所 差 異 非 虛 擬 函 式 : 若 某 函 式 為 類 別 架 構 內 的 所 有 類 別 共 同 擁 有 的 功 能 或 特 徵, 且 不 會 因 類 別 的 不 同 而 運 算 方 式 有 所 差 異 一 般 成 員 函 式 : 函 式 僅 是 某 類 別 所 特 有 的 功 能 76 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 38
各 種 成 員 函 式 的 使 用 時 機 ( 二 ) 幾 何 範 例 類 別 : 幾 何 圖 形 (Geometric_Entity) 三 角 形 (Triangle) 圓 (Circle) 函 式 : 計 算 周 長 (perimeter) 面 積 (area) 顯 示 顏 色 (display_color) 圓 心 (circle_center) 內 接 圓 圓 心 (incenter) 77 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 各 種 成 員 函 式 的 使 用 時 機 ( 三 ) 類 別 關 係 : 每 一 個 三 角 形 與 圓 形 都 是 一 個 幾 何 圖 形 struct Point { double x, y ; } ; enum Color { red, green, blue, cyan, yellow } ; class Geometric_entity { protected : Color entity_color ; } ; class Triangle : public Geometric_Entity { private : Point pt1, pt2, pt3 ; } ; class Circle : public Geometric_Entity { private : } ; Point center ; double radius ; // 圓 心 // 半 徑 // 幾 何 圖 形 的 顏 色 // 三 頂 點 座 標 78 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 39
各 種 成 員 函 式 的 使 用 時 機 ( 四 ) 函 式 分 類 周 長 面 積 為 所 有 圖 形 的 共 同 功 能 但 圖 形 不 同, 計 算 方 式 也 不 同 虛 擬 函 式 顯 示 顏 色 為 所 有 圖 形 的 共 同 功 能, 但 顯 示 方 式 不 因 類 別 不 同 而 有 所 差 異 非 虛 擬 函 式 圓 心 內 接 圓 圓 心 為 圓 形 類 別 所 特 有 的 功 能 圓 形 類 別 內 的 一 般 成 員 函 式 79 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 各 種 成 員 函 式 的 使 用 時 機 ( 五 ) 成 員 函 式 定 義 class Geometric_entity {... public : virtual double perimeter() const {... } virtual double area() const {... } Color display_color() const {... } } ; class Triangle : public Geometric_Entity {... public : virtual double perimeter() const {... } virtual double area() const {... } Point incenter() const {... } } ; class Circle : public Geometric_Entity {... public : virtual double perimeter() const {... } virtual double area() const {... } Point circle_center() const {... } } ; 80 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 40
抽 象 基 礎 類 別 與 純 虛 擬 函 式 ( 一 ) 抽 象 基 礎 類 別 (abstract base class) 不 能 產 生 實 體 物 件 的 基 礎 類 別 交 通 工 具 火 車 飛 機 馬 車 交 通 工 具 的 實 體 都 是 屬 於 衍 生 類 別 的 物 件, 交 通 工 具 為 所 有 衍 生 類 別 的 公 約 數, 無 實 體 可 言 81 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 抽 象 基 礎 類 別 與 純 虛 擬 函 式 ( 二 ) 純 虛 擬 函 式 無 實 作 程 式 碼 的 虛 擬 函 式 class Vehicle { public : virtual bool use_engine() const = 0 ; 在 語 法 上 純 虛 擬 函 式 為 虛 擬 函 式 末 尾 加 上 = 0 82 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 41
抽 象 基 礎 類 別 與 純 虛 擬 函 式 ( 三 ) 純 虛 擬 函 式 無 實 作 碼, 因 此 所 有 繼 承 此 類 別 的 衍 生 類 別 都 須 要 定 義 此 虛 擬 函 式 的 實 作 程 式 碼 class Car : public Vehicle {... public : bool use_engine() const { return true ; } } ; class Horse_wagon : public Vehicle {... public : bool use_engine() const { return false ; } } ; 83 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 抽 象 基 礎 類 別 與 純 虛 擬 函 式 ( 四 ) 抽 象 基 礎 類 別 (ABC) 至 少 含 有 一 個 純 虛 擬 函 式 的 基 礎 類 別 class Vehicle { public : virtual bool use_engine() const = 0 ; 以 上 Vehicle 為 抽 象 基 礎 類 別 84 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 42
抽 象 基 礎 類 別 與 純 虛 擬 函 式 ( 五 ) 抽 象 類 別 不 能 產 生 物 件, 卻 可 用 來 當 成 衍 生 類 別 物 件 的 參 考 或 指 標 Vehicle a ; // 錯 誤,Vehicle 是 一 個 抽 象 類 別 Car b ; Vehicle &c = b ; // c 為 汽 車 類 別 物 件 b 的 參 考 物 件 Vehicle *d = new Horse_wagon ; Vehicle *e = &d ; // d 為 一 抽 象 類 別 指 標 指 到 馬 車 類 別 // e 為 一 抽 象 類 別 指 標 指 到 馬 車 類 別 85 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 抽 象 基 礎 類 別 與 純 虛 擬 函 式 ( 六 ) 抽 象 類 別 仍 可 以 使 用 建 構 函 式 來 設 定 其 內 的 資 料 成 員 class Car { protected : int passanger_no ; public : Car( int no ) : passanger_no(no) {} virtual int tire_no() const = 0 ; } ; class Sedan : public Car {... public : Sedan( int no = 5 ) : Car(no){ } ; 為 避 免 建 構 函 式 被 誤 用, 可 以 將 其 放 到 保 護 區 內 隱 藏 起 來 class Car { protected : int passanger_no ; Car( int no ) : passanger_no(no) {} } ; 86 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 43
類 別 架 構 下 的 型 別 轉 換 ( 一 ) 若 有 一 類 別 架 構 如 右 CAR Car *car = new Sedan ; Sedan *sedan ; Sedan RV sedan = car ; // 錯 誤, 無 法 將 Car 指 標 轉 成 Sedan 指 標 上 式 的 左 邊 sedan 為 指 向 Sedan 的 指 標, 右 邊 car 為 指 向 Car 的 指 標, 無 法 在 靜 態 型 別 間 轉 型 87 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 類 別 架 構 下 的 型 別 轉 換 ( 二 ) dynamic_cast: 動 態 型 別 的 轉 換 int kind ; Car *car ; Sedan *sedan1 ; cin >> kind ; if ( kind == 1 ) car = new Sedan ; // 執 行 時 才 產 生 一 轎 車 物 件 else car = new RV ; // 執 行 時 才 產 生 一 休 旅 車 物 件 sedan1 = dynamic_cast<sedan&>(car) ; // 使 用 指 標 Sedan &sedan2 = dynamic_cast<sedan&>(*car) ;// 使 用 參 考 Sedan &sedan3 = dynamic_cast<sedan>(*car) ; // 錯 誤, 須 要 參 考 88 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 44
類 別 架 構 下 的 型 別 轉 換 ( 三 ) 動 態 轉 型 不 見 得 會 成 功, 轉 型 後 都 要 測 試 Car *car ; // 定 義 Car 指 標... Sedan *sedan = dynamic_cast<sedan*>(car) ; // 確 定 是 否 轉 型 成 功 if ( sedan ) cout << sedan->tire_no() << endl ; else cout << 動 態 轉 型 失 敗 << endl ; 當 指 標 類 別 動 態 轉 型 失 敗 時,C ++ 會 回 傳 0 給 指 標 89 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 各 種 繼 承 函 式 的 比 較 基 礎 類 別 的 函 式 型 別 非 虛 擬 函 式 一 般 虛 擬 函 式 純 虛 擬 函 式 衍 生 類 別 所 繼 承 的 內 容 繼 承 函 式 介 面 與 其 程 式 的 實 作 部 分 繼 承 函 式 介 面 與 備 用 的 程 式 實 作 部 分 僅 繼 承 函 式 介 面 90 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 45
大 學 學 院 學 系 類 別 ( 一 ) 相 關 類 別 University 大 學 College 學 院 Dept 學 系 Science 理 學 院 Engineering 工 學 院 類 別 關 係 每 個 大 學 包 含 著 若 干 學 院 -> has a -> 嵌 入 每 個 學 系 包 含 著 若 干 學 系 -> has a -> 嵌 入 理 學 院 工 學 院 是 學 院 -> is a -> 公 共 繼 承 91 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 大 學 學 院 學 系 類 別 ( 二 ) 類 別 程 式 class University { private : string name ; vector<college> colleges ;... } ; class College { protected : string name ; vector<string> depts ; } ; // 學 校 的 名 稱 // 學 校 內 的 學 院 // 學 院 的 名 稱 // 學 院 內 的 學 系 class Science : public College {.. // 理 學 院 是 個 學 院 class Engineering : public College {.. // 工 學 院 是 個 學 院 92 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 46
大 學 學 院 學 系 類 別 ( 三 ) 學 院 為 一 抽 象 概 念, 須 利 用 純 虛 擬 函 式 設 定 其 為 抽 象 基 礎 類 別, 同 時 要 將 University 類 別 的 vector<college> vector<college*> 以 避 免 學 院 類 別 物 件 的 建 立 程 式 碼 連 結 輸 出 93 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 租 車 商 車 子 管 理 ( 一 ) 若 車 子 類 別 架 構 為 Car RV Limousine Car 為 抽 象 基 礎 類 別 94 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 47
租 車 商 車 子 管 理 ( 二 ) 物 件 使 用 方 式 vector<car*> cars ; cars.push_back( new RV(...) ) ; cars.push_back( new Limousine(...) ) ;... RV *rv ; // 僅 列 印 cars 陣 列 中 所 有 的 RV 車 資 料 for ( int i = 0 ; i < cars.size() ; ++i ) { if ( rv == dynamic_cast<rv*>(cars[i]) ) cout << *rv << endl ; } 程 式 碼 連 結 輸 出 95 類 別 間 的 關 係 ( 一 ) : 嵌 入 與 繼 承 48