繼承的優點 程式碼再使用 (code reuse) 抽象概念再使用 類別階層化 澄清物件間的關係.

Slides:



Advertisements
Similar presentations
第一單元 建立java 程式.
Advertisements

项目7 面向对象高级.
第四章 继承与派生 Chapter 4 Inheritance and Derivation
第一章 面向对象程序设计.
第11章 使用类.
第6章 多态性与虚函数.
程設一.
11 繼承類別 11.4 建立者與破壞者 單一建立者與破壞者 11-20
類別與物件 Class & Object.
第15章 繼承與多重繼承 15-1 繼承的基礎 15-2 覆寫與隱藏父類別的成員 15-3 子類別的建構與解構子 15-4 多重繼承
第7单元 面向过程编程—— 继承与多态.
Virtual Function Jing(井民全).
鄭士康 國立台灣大學 電機工程學系/電信工程研究所/ 資訊網路與多媒體研究所
程設一.
刘胥影 东南大学计算机学院 面向对象程序设计1 2010~2011第3学期 刘胥影 东南大学计算机学院.
走向C++之路 WindyWinter WindyWinter感谢诸位前来捧场。
Java簡介.
struct 可以在同一個名稱下擁有多種資料型態。使用struct能讓資料的存取和處理更為靈活。
物件導向程式設計 (Object-Oriented rogramming)
内容提要 对象的生命周期 构造函数 析构函数 拷贝构造函数. 常宝宝 北京大学计算机科学与技术系
Derived Class 前言 衍生類別的定義 單一繼承 public, protected, 和 privated 基底類別
刘胥影 东南大学计算机学院 面向对象程序设计1 2011~2012第3学期 刘胥影 东南大学计算机学院.
程式敘述執行順序的轉移 控制與重複、方法 Lecturer:曾學文.
第11章 运算符重载 什么是运算符重载 运算符重载的方法 几个特殊的运算符的重载 自定义类型转换运算符 运算符重载实例.
·线性表的定义及ADT ·线性表的顺序存储结构 ·线性表的链接存储结构 · 单向循环链表 · 双链表、双向循环链表 · 一元多项式的加法
第六章 继承性和派生类 胡昊 南京大学计算机系软件所.
第十五章 Linked List, Stack and Queue
西安交通大学 计算机教学实验中心 大学C++程序设计教程 西安交通大学 计算机教学实验中心
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
程序设计期末复习 黎金宁
第三章 C++中的C 面向对象程序设计(C++).
2 C++ 的基本語法和使用環境 親自撰寫和執行程式是學好程式語言的不二法門。本章藉由兩個簡單的程式,介紹C++ 程式的基本結構和開發環境,讓初學者能逐漸建立使用C++ 的信心。
類別(class) 類別class與物件object.
Object-Oriented Programming: Polymorphism
C#面向对象程序设计 $7 继承和多态性.
第6章 继承和接口设计 6.1 继 承 6.2 多态性 6.3 抽象类 6.4 接口 6.5 接口在集合排序中的应用.
五、链 表 1、单链表 2、双向链表 3、链表应用.
繼承概念的優點 類別再使用(程式碼再使用) 抽象化概念再使用 類別關係階層化.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
第三章 链表 单链表 (Singly Linked List) 循环链表 (Circular List) 多项式及其相加
第七章 操作符重载 胡昊 南京大学计算机系软件所.
第一單元 建立java 程式.
第16章 虛擬與多形 16-1 虛擬函數 16-2 純虛擬函數與抽象類別 16-3 多形 16-4 虛擬繼承與虛擬解構子.
10 多載函數 10.1 多載概論 多載一般函數 多載成員函數 10-3
第7章 繼承/多型/介面 注意: 本投影片僅供本書上課教師使用,非經同意請勿上網轉載或供拷貝.
二叉树的遍历.
第三章 链表 单链表 循环链表 多项式及其相加 双向链表 稀疏矩阵.
常宝宝 北京大学计算机科学与技术系 数据结构(三) 常宝宝 北京大学计算机科学与技术系
C++大学基础教程 第11章 多态性 北京科技大学 信息基础科学系 2019/4/8 北京科技大学.
第五章 递归与广义表 递归的概念 递归过程与递归工作栈 递归与回溯 广义表.
潘爱民 C++ Overview 潘爱民
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
Inheritance -II.
樣版.
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
C++程序设计 吉林大学计算机科学与技术(软件)学院.
第九章 物件導向-進階.
12 虛擬函數 12.1 多載與超載 12-2 多載函數 12-2 超載函數 虛擬函數 12-6 同名異式 12-7
#include <iostream.h>
第二章 Java基本语法 讲师:复凡.
C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计.
第一讲 面向对象方法学与信息系统建模.
C++语言程序设计 第十章 C++标准模板库 成都信息工程学院计算机系.
谭浩强编著 C++面向对象程序设计 授课教师:姬广永 学习网站:
《数据结构与算法设计》第一部分 面向对象的C++程序设计基础.
第四章 陣列、指標與參考 4-1 物件陣列 4-2 使用物件指標 4-3 this指標 4-4 new 與 delete
13 繼承類別 13.1 繼承概論 基礎類別與衍生類別 繼承型式 13-2
資料結構與C++程式設計進階 C++與資料結構 講師:林業峻 CSIE, NTU 7/ 5, 2010.
方法(Method) 函數.
InputStreamReader Console Scanner
Presentation transcript:

繼承的優點 程式碼再使用 (code reuse) 抽象概念再使用 類別階層化 澄清物件間的關係

繼承與Code Reuse(被動) 類別庫 函式庫 (.lib .dll) 主計劃 子計劃1 子計劃2 子計劃3 (你所在的組)

繼承與Code Reuse class List { …… void insert() {…} void delete() {…} } ; (1) 功能不足 (2) 原有功能不佳 class List { …… void insert() {…} void delete() {…} } ; 重新改寫??? (1) 原始碼在哪? (2) 還有其他使用者,是否都同意改寫? 使用繼承來改善

繼承與Code Reuse class List {….. insert(int n) ;…. delete(int pos);}; class List1: public List { node& operator[](int index) ; //新增 void insert(int n) ; // 修改: 更高效率的實作方式 }; void main() { List1 L; ….. ; L.insert(15) ; cout << L[3] ; }

可能結果 類別庫 (List,Stack…) 主計劃 子計劃1 (List1) 子計劃2 (List2) 子計劃3 (沿用List)

繼承與Code Reuse(主動) Q: 設計一物件導向資料庫: 儲存學校學生資料 [先修生] 學號 系級 高中校名 選課() 註冊() [僑生] 學號 系級 e-mail 國籍 選課() 註冊() 工讀() [交換學生] 學號 系級 e-mail 國籍 選課() 註冊() 定期約談() [一般生] 學號 系級 e-mail 選課() 註冊() 工讀()

作業: list  stack struct node {int info; node* next; }; class list { node *head, *tail ; int node_no ; public: list() ; list(const node& n) ; list(const list& L) ; ~list() ; int getSize() ; void insert(int pos, int value) ; // 0: first, node_no:last void delete(int pos) ; // 刪除第pos個元素 void show(string msg) ; //印出串列內容 list& operator=(const list& L) ; friend list operator+(const list& L1, const list& L2) ; //聯集 friend list operator*(const list& L1, const list& L2) ; //交集 friend list operator-(const list&L1, const list& L2) ; //差集 } ;

使用list產生stack class stack: public list { stack() ; ~stack() ; operator=(const stack& s) ; void push(int x) ; //加在list的最前端 int pop() ; //刪除list的第一個元素 // list中的operator+, -, * 是否也被繼承? } ;

測試class list void main() { list L1, L2, L3 ; for (int i = 101; i<=108; i++) L1.insert(L1.getSize(),i) ; for (int j = 110; j>=105; j--) L2.insert(L2.getSize(), j) ; L1.show(“L1=“); L2.show(“L2=“) ; L3 = L1 + L2 ; L3.show(“L3=L1+L2=“) ; L3 = L1 * L2; L3.show(“L3=L1*L2=“) ; L3 = L1 – L2; L3.show(“L3=L1-L2=“) ; L3.delete(1) ; L3.delete(2) ; L3.show(“after 2 delete, L3=“) ; stack s1, s2 ; for (int k=1; k<=10; k++) { if (k%3==0) s1.pop(); s1.push(k) ; s1.show(“s1=“) ; } s2 = s1; s2.show(“s2=“) ;

第十章 多型與虛擬函數 (Polymorphism & Virtual Functions) 10-1 衍生類別的指標 10-2 簡介虛擬函數 10-3 虛擬函數的細節 10-4 應用多型

多型 編譯時期多型(靜態多型) 執行時期多型 (或動態多型) function overloading 如何正確呼叫同名的函數? 利用參數個數與型態 operator overloading 其實同function overloading 執行時期多型 (或動態多型) 如何正確呼叫不同物件的相同名稱的成員函數  利用繼承與多型

衍生類別與基底類別物件間的指定(assignment) class base { int x ; public: setx(int n) { x=n;} } ; class derived: public base { int y ; setx(int n) { base::setx(3*n);} sety(int n) { y = n;} void main() { base b ; derived d ; b = d ; // 可乎? b.setx(5) ; // 哪個setx() b.sety(10); //? d = b ; // ? d.setx(5) ; d.sety(8); // ? }

結論 base Obj = derived Obj (可) void main() { base b ; derived Obj = base Obj (否) void main() { base b ; derived d ; b = d ; // 可 b.setx(5) ; // 哪個setx() b.sety(10); //? 否 d = b ; // ?否 d.setx(5) ; d.sety(8); // ?可

10-1 衍生類別的指標 case 2 Case 1 void main() { void main() { base *pb ; derived *pd ; base b; derived d ; pd = &b ; // ??? 否 pd->setx(5) ; // ?否 } Case 1 void main() { base *pb ; base b; derived d ; pb = &b ; // Sure! pb->setx(5) ; pb = &d ; // 可乎? pb->setx(5) ; // 哪個? pb->sety(10); // ? 否 }

衍生類別的參考(reference) case 2 void main() { base b; derived d ; derived &refd1 = b ; //?否 refb1.setx(5) ; } Case 1 void main() { base b; derived d ; base &refb1 = b ; // sure refb1.setx(5) ; // 哪個? base base& refb2 = d ; // ?? 可 refb2.setx(5) ; refb2.sety(10); // ?? 否 }

結論: 自己寫 base-pointer = &derived-Obj (可) base-reference = derived-Obj (可) derived-pointer = &base-Obj (否) derived-reference = base-Obj (否)

10-2 多型與虛擬函數 甚麼是執行時期的多型? 是否能呼叫到 正確的move() 與stop(); class car { … move() ; …stop();} ; class Benz: public car {…move() ; …stop();} ; class Volvo: public car {…move() ; …stop(); } ; class Civic: public car {…move() ; … stop(); } ; void main() { Benz b; Volvo v; Civic c ; demo(b); demo(v); demo(c) ; } void demo(car& c) { c.move() ; c.stop() ;}

不使用虛擬函數 實際try! 輸出結果為何? car move class car { public:void move() { cout << “car move”;} } ; class Benz: public car { public:void move() { cout << “Benz move”;} class Volvo: public car { public:void move() { cout << “Volvo move”;} void demo(car& c) { c.move() ; } void main(){Benz b;Volvo v;demo(b);demo(v);}

甚麼是虛擬函數? 是一種宣告在基底類別中的成員函數 提供執行時期多型的機制 使用virtual保留字 通常衍生類別會override它

使用虛擬函數 (配合reference) 實際try! class car { 輸出結果為何? Benz move Volvo move class car { virtual void move() { cout << “car move”;} } ; class Benz: public car { void move() { cout << “Benz move”;} class Volvo: public car { void move() { cout << “Volvo move”;} void demo(car& c) { c.move() ; } void main() { Benz b ;Volvo v; demo(b); demo(v) ; } 

使用虛擬函數(配合pointer) 實際try! 輸出結果為何? Benz move Volvo move class car { virtual void move() { cout << “car move”;} } ; class Benz: public car { void move() { cout << “Benz move”;} class Volvo: public car { void demo(car *pc) { pc->move() ; } void main() { Benz b ;Volvo v; demo(&b); demo(&v) ; } 

使用虛擬函數 (配合物件傳遞) 實際try! 輸出結果為何? car move class car { virtual void move() { cout << “car move”;} } ; class Benz: public car { void move() { cout << “Benz move”;} class Volvo: public car { void demo(car c) { c.move() ; } void main() { Benz b ;Volvo v; demo(b); demo(v) ; } 

不使用多型可以嗎? 多型: 一個介面多種用法 不多型: void move(car& c) { c.move() ; ….} void move(void *p, int type) { switch(type){ case 1: ((Benz *)p)->move(); break ; case 2: ((Volvo *)p)->move(); break ; …… }

練習 class plane { virtual void fly() { takeoff(); onAir(); landing();} void onAir() {……} void takeoff() {……} void landing() {……} } ; // 你不滿意takeoff的行為該如何?

Plane class plane{ public: virtual void fly() { takeoff(); onAir(); landing();} void onAir() {cout<<"onAir"<<endl;} virtual void takeoff() {cout<<"takeoff"<<endl;} void landing() {cout<<"landing"<<endl;} }; class F16:public plane{ public: // void fly(){cout<<"F16 fly"<<endl;} void takeoff(){cout<<"F16 takeoff"<<endl;} }; class B747:public plane{ // void fly(){cout<<"B747 fly"<<endl;} void takeoff(){cout<<"B747 takeoff"<<endl;} void demo(plane &p){p.fly();} void main() { B747 b; F16 f; demo(b); demo(f); }

Case Study: p. 10-19 list store(x); retrieve(); head #1 #2 #n 如何利用list來模擬(實作) stack與queue stack queue retrieve store #1 #2 #n #1 store retrieve #n

繼承示意圖 class list { … virtual void store(int i) ; virtual int retrieve() ; } ; class queue: public list { … void store(int i) ; int retrieve() ; } ; class stack: public list { … void store(int i) ; int retrieve() ; } ;

10-3 更多虛擬函數的細節 純粹虛擬函數(pure virtual function) 抽象類別(abstract class) class printer { string filename ; public: void reset() {… } virtual void print(int m)=0 ; } 抽象類別(abstract class) 當類別至少含有一個純粹虛擬函數時 不能用來產生物件 e.g. printer p ; //XX

純粹虛擬函數的內容 純粹虛擬函數(pure virtual function) class printer { string filename ; public: virtual void reset()=0; virtual void print(int mode)=0 ; }

純粹虛擬函數的特性 衍生類別一定要override 基底類別中所有的純粹虛擬函數 class printer {…...}; class HPLaserJet6L: public printer { …… void reset() { …自己的版本…} void print(int mode) {…自己的版本…} };

抽象類別的用途(一) 設計共同的使用介面的類別(衍生類別負責實作) class shape { string name ; public: virtual void draw(char b[][80])=0 ; // 不必有實作 virtual void clear()=0 ; //不必有實作 }; class triangle: public shape {………} ; class circle: public shape {……};

抽象類別的用途(二) 防止使用者產生不允許存在的物件 class shape { string name ; public: virtual void draw()=0 ; }; class triangle: public shape {………} ; class circle: public shape {……}; void main() { shape s ; /* what ??? */ ….. }

10-4 應用多型 早期繫結(early binding)或編譯時期繫結(compiling time binding) 一般函數 超載函數 夥伴函數 非虛擬之成員函數 晚期繫結(late binding)或執行時期繫結(run-time binding) 虛擬函數 (效率較差)

例子 early binding late binding void fun(int x) { cout << x; } void main() { fun(5) ; // early binding late binding // 承前例 void move(car& c) { c.move() ; // late binding } void main() { Benz b; Volvo v ; int x ; cin >> x ; if (x%2) b.move(); …..

繼承與Code Reuse(主動) Q: 設計一物件導向資料庫: 儲存學校學生資料 [先修生] 學號 系級 高中校名 選課() 註冊() [僑生] 學號 系級 e-mail 國籍 選課() 註冊() 工讀() [交換學生] 學號 系級 e-mail 國籍 選課() 註冊() 定期約談() [一般生] 學號 系級 e-mail 選課() 註冊() 工讀()

練習 class student { protected: string studID, name, eMail ; public: void fillData()=0 ; void getID() { return ID; } void show()=0 ; } ; class LocalStudent: public student { string ID ; …… } class AbroadStudent: public student { string passportID; string country ;……

續 class IMStudents { const int MAX_STUD ; student *stud[720] ; public: students(string filename=“”):MAX_STUD(720) { } void addData(string ID) ; int search(string ID) ; } ; void main() { IMStudents ims(“Imdata.txt”) ; while (true) { }