繼承概念的優點 類別再使用 ( 程式碼再使用 ) 抽象化概念再使用 類別關係階層化 1
2-3 簡介繼承 Q: Q: 人 黑猩猩與猴子的有哪些共同屬性? 繼承 靈長類特徵 (( 屬性 )) -- 手 足 脊椎 大拇指型態行為 :: -- 育兒 :: 哺乳 -- 使用工具 人類 黑猩猩 彌猴 人類是靈長類的一種 人類繼承了靈長類應有的特徵及行為 人類繼承了靈長類 2
繼承的概念 員工 (employee) [ 屬性 ]: 姓名 年齡 年資 年薪 [ 動作 ]: 計算健保扣除額 計算所得稅繼承 工人 課員 課長 主任 經理 3
繼承階層圖 員工 (employee) [ 屬性 ]: 姓名 年齡 年資 年薪 [ 動作 ]: 計算健保扣除額 計算所得稅繼承 工人 課員 課長 主任 經理 搬運工 作業員 包裝工繼承了員工 工人 作業員的所有特性 包裝工 食料調製工 4
請問包裝工的屬性與動作?特性的再使用 新增與修改 員工 (employee) [ 屬性 ]: 姓名 年齡 年資 年薪 [ 動作 ]: 計算健保扣除額 計算所得稅 繼承 搬運工 工人 包裝工 [ 屬性 ] 加班時數 作業員 New Override [ 動作 ] 職業訓練, 計算所得稅 食料調製工 New 5
特性的再使用 新增與修改 (1) 直接繼承 (2) 新增屬性或動作 (3) 修改屬性或動作 靈長類 ( 上古狐猴 ) 靈長類 ( 上古狐猴 ) ( 三 ) ( 二 ) 人類 猩猩 ( 一 ) 猴子 [ 屬性 ]: 膚色 New [ 動作 ] 直立行走使用工具 New Override [ 動作 ] 手語 New Nothing New 6
基底類別 (basis class) 與 衍生類別 (derived class) Basis class (Parent class) 靈長類 ( 上古狐猴 ) 靈長類 ( 上古狐猴 ) 繼承 人類 Derived class (Child class) 繼承 猩猩 Derived class (Child class) 繼承 猴子 Derived class (Child class) 7
一 直接繼承 繼承的語法 class B { int i ; // 屬性 // 動作 void set_i(int n) { i = n;} int get_i() { return i; } }; class D: public B { class D 繼承了 class B class D 繼承了 class B class B class D 8
直接繼承 class B { int i ; // 屬性 // 動作 void set_i(int n) { i = n;} int get_i() { return i; } }; class D: public B { Q: class D 有哪些資料成員? 成員函數? i B set_i(), get_i() i D set_i(), get_i() 9
使用衍生類別 class B {.get_i(); set_i(int n) ;.. class D: public B { void main() { D ob ; ob.set_i(10) ; cout << ob.get_i() <<endl ; } 10
衍生類別的內容 ( 或任務 ) (1) 直接繼承 (2) 新增屬性或動作 (3) 修改屬性或動作 靈長類 ( 上古狐猴 ) 靈長類 ( 上古狐猴 ) 人類 猩猩 猴子 [ 屬性 ]: 膚色 New [ 動作 ] 直立行走使用工具 New Override [ 動作 ] 手語 New Nothing New 11
二 新增成員 class OneDim{ int x ; void setx(int n) { x = n ;} void showx() {cout << x <<endl ; } class TwoDim: public OneDim { int y ; // 新增的 data memeber void sety(int n) { y = n ;} // 新增的 member functions void showy() {cout << y << endl ; } // 新增的 functions class TwoDim 的成員 int x; x; int y ;; setx(int n) n) ;; showx() ;; sety(int n) n) ;; showy() ;; 12
使用 class TwoDim void main() { TwoDim td ; td.setx(5) ; // 基底類別 td.sety(10) ; // 衍生類別 td.showx(); // 基底類別 td.showy() ; // 衍生類別 // try, 可乎? td.x = 10 ; td.y = 20 ; } class TwoDim 的成員 int x; x; int y ;; setx(int n) n) ;; showx() ;; sety(int n) n) ;; showy() ;; 對外界 ( 類別使用者 ) 而言,TwoDim 的成員中哪些是 private? 哪些是 public? 13
在衍生類別中使用基底類別成員 class OneDim{ int x ; void setx(int n) { x = n ;} void showx() {cout << x <<endl ; } class TwoDim: public OneDim { int y; void setxy(int a, int b) { x= a; y = b ;} void showxy() {cout << x << << y << endl ; } class TwoDim 的成員 int intx; x; int inty ;; setx(int n) n) ;; showx() ;; setxy(int a, a, int intb) b) ;; showxy() ;; Q: Q: 子類別可以取用父類別中的私有成員? 14
在衍生類別中使用基底類別成員 class OneDim{ int x ; void setx(int n) { x = n ;} void showx() {cout << x <<endl ; } class TwoDim: public OneDim { int y; void setxy(int a, int b) { setx(a); y = b ;} void showxy() { showx(); cout << y << endl ; } 仔細觀察與上例有何差異? 15
父類別成員存取權 基底類別 衍生類別 衍生類別使用者 private public public 繼承 private public 16
父類別成員存取權 基底類別 衍生類別 private public public 繼承 private public 17
EX: 完成以下程式 class ThreeDim: public TwoDim { int z ; setxyz(int a, int b, int c) {.} showxyz() {.} 先寫出 ThreeDim 有哪些成員? 18
三 修改基底類別成員 class TwoDim { int x, y ; void setxy(int a, int b) { x = a; y = b; } void show() { cout << x << << y ;} }; Q: 寫出 ThreeDim 的成員? Q: 寫出 ThreeDim 的成員? class ThreeDim :public TwoDim { int z; void setxyz(int a, int b, int c) {setxy(a, b); z = c ; } void show() { TwoDim::show(); cout << << z ;} Override: 將父類別的函數重新定義一次 (( 函數名稱 回傳值均相同 )) 19
使用 ThreeDim void main() { ThreeDim point3d ; point3d.setxyz(1,2,3) ; // 呼叫誰的 set() point3d.show() ; // 呼叫誰的 show() } 20
EX: 回答以下問題 class TwoDim { int x, y ; void set(int a, int b) { x = a; y = b; } void show() { cout << x << << y ;} }; class ThreeDim :public TwoDim { int z; void set(int a, int b, int c) {.} void show() { TwoDim::show(); cout << << z ;} Q1: 完成 set(int a, a, int intb, b, int intc) c) Q2: 寫出 ThreeDim 的成員? Q3: set() 算不算 override? 21
2-3 範例一 fruit name, color getname() getcolor() set(name, color) color: red, yellow, green, orange Apple cooking set(name, color, cooking) show() Orange juicy set(name, color, juicy) show() 22
main() void main() { Apple a; Orange o ; a.set( Washington, red, yes) ; a.show(); o.set( Sunkys, orange, false) ; b.show() ; } 23
繼承的用處 描述物件間 is-a-kind of 的關係 提昇程式碼的再使用率 有利於類別的更新與修正 24
描述物件之間的關係 has-a Each man has two legs class man { Leg legs[2] ; is-a-kind-of 工讀生是學校員工的一種 人是一種靈長類 25
增加程式碼的再使用率 class TwoDim { int x, y ; void setxy(int a, int b) { x = a; y = b; } void show() { cout << x << << y ;} } class ThreeDim { int z; void setxyz(int a, int b, int c) {setxy(a, b); z = c ; } void show() { TwoDim::show(); cout << << z ;} } 26
有利於類別的更新與修正 當你使用的類別庫設計不良或有所不足時, 該如何? // 你覺得需要一個 int sum(); // 你覺得 delete(int value) 效率很差 class list {. // data member void insert(int n) {.} void delete(int value) { } void show() { } 27
後記 : 回憶 Window Programming #include <afxwin.h> // 載入 afxwin 標頭檔 class MyApp : public CWinApp // 繼承 CWinApp { BOOL InitInstance() // 程式進入點 { CFrameWnd *Frame = new CFrameWnd(); // 建立 CFrameWnd 物件 ( 產生 ) m_pmainwnd = Frame; // 將 m_pmainwnd 設定為 Frame Frame->Create(NULL,"Hello MFC"); // 建立視窗 ( 建立 ) Frame->ShowWindow(SW_SHOW); return true; } }; MyApp a_app; // 建立應用程式物件 28
7-2 使用保護成員 class OneDim { int x; void setx(int a) { x = a ; } void getx() { return x ; } class TwoDim:public OneDim { int y ; void distance(twodim& pt) { } } Q: Q: 我可否直接在 TwoDim 取用 x? x? Q: 缺點? return sqrt(pow(getx()-pt.getx(),2), pow(y-pt.y, 2)) ; 29
需求 我想在子類別中直接使用父類別的私有成員, 但是外界仍不可直接存取這個成員 將私有成員改成保護成員 30
範例一 class samp { int a ; protected: int b ; int c ; samp(int n, int m) { a = n; b=m; } void main() { samp ob(10, 20) ; ob.a = 10; ob.b = 20; ob.c = 30 ; } 31
範例二 class base { protected: int a, b ; void setab(int n, int m) { a= n ; b=m;} class derived: public base { int c ; void setc(int n) {c = n ;} void show() { cout << a << << b << << c <<endl ;} void main() { derived d; d.setab(10,20); d.setc(30); d.show(); } 32
7-1 基底類別存取控制 class OneDim { } class TwoDim: public OneDim { } 33
公有繼承 (public) class Base { private: int a ; protected: int b; int c; class Derived: public Base { // int a; private // int b; protected // int c; public }; void main() { Derived d ; // a, b: private // c: public } 34
私有繼承 (private) class Base { private: int a ; protected: int b; int c; class Derived: private Base { // int a; private // int b; private // int c; private }; void main() { Derived d ; // a, b, c: private } 35
保護繼承 (protected) class Base { private: int a ; protected: int b; int c; class Derived: protected Base { // int a; private // int b; protected // int c; protected }; void main() { Derived d ; // a, b, c: private } 36
7-3 建構子 解構子與繼承 以下成員不會被子類別繼承 (1) 建構子 解構子與 operator=() (2) 夥伴函數 class B { int x ; B(int n) { x = n ;} class D: public B { void main() { D d(10) ; } 37
物件欄位的生成消滅次序 class employee { string name ; int ID ; class worker: public employee { float overtime ; void main() { worker w ; } name ID Overtime 38
範例一 : 生成與消滅的次序 class base { base() { cout << base constructing <<endl;} ~base() { cout << base destructing <<endl;} class derived: public base { derived() { cout << derived constructing <<endl;} ~derived() { cout << derived destructing <<endl;} base constructing derived constructing derived destructing base destructing 39
範例二 : 傳引數給衍生類別建構子 class base { base() { } ~base() { } class derived: public base { int j ; derived(int n) { j = n ;} ~derived() { } }; void main() { } derived ob(10) ; 40
成員的初始化 : 使用 Initializer class point { int x, y ; public point(const point& p):x(p.x), y(p.y) { } class triangle { point pt1, pt2, pt3; triangle(point p1, point p2, point p3):pt1(p1), pt2(p2), pt3(p3) {} 41
範例三 class base { int i ; base(int n) { i =n;} // 接 class derived void main() { derived d1(10) ; // i=j=10 derived d2(5, 3) ; //i=5,j=3 } class derived: public base { int j ; derived(int n):base(n){ j = n ; } derived(int a, int b):base(a) { j = b; } }; 42
練習題 (p. 7-19) 習題一 習題二 43