第15章 繼承與多重繼承 15-1 繼承的基礎 15-2 覆寫與隱藏父類別的成員 15-3 子類別的建構與解構子 15-4 多重繼承

Slides:



Advertisements
Similar presentations
系統分析與設計 楊子青 H-1 H 、物件導向技術 n 物件導向的基本概念 – 物件、類別 – 封裝、繼承 – 同名異式 ( 多型 ) 、超荷 ( 過載 ) n 物件導向分析與設計及塑模工具 n UML 塑模工具.
Advertisements

第四章 类、对象和接口.
项目7 面向对象高级.
Ch02物件導向程式設計 物件導向系統分析與設計.
四資二甲 第三週作業 物件導向程式設計.
第一章 面向对象程序设计.
设计模式可以帮助我们改善系统的设计,增强 系统的健壮性、可扩展性,为以后铺平道路。
第6章 多态性与虚函数.
類別與物件 Class & Object.
類別的繼承-一般關係: 繼承是宣告的類別繼承現存類別的部份或全部的成員資料和方法 , 新增額外的成員資料和方法或覆寫和隱藏繼承類別的方法
第7单元 面向过程编程—— 继承与多态.
C++程序设计 王希 图书馆三楼办公室.
鄭士康 國立台灣大學 電機工程學系/電信工程研究所/ 資訊網路與多媒體研究所
第5章 面向对象程序设计 本章要点 5.1 面向对象程序设计概述 5.2 Java语言的面向对象程序设计 5.3 方法的使用和对象数组
走向C++之路 WindyWinter WindyWinter感谢诸位前来捧场。
H、物件導向技術 物件導向的基本概念 物件、類別 封裝、繼承 同名異式(多型) 、超荷(過載) 物件導向分析與設計及塑模工具 UML塑模工具.
内容提要 对象的生命周期 构造函数 析构函数 拷贝构造函数. 常宝宝 北京大学计算机科学与技术系
4.1 概述 4.2 类与对象的实现 4.3 对象的初始化和析构 4.4 类的包含 4.5 类模板
Derived Class 前言 衍生類別的定義 單一繼承 public, protected, 和 privated 基底類別
Classes Lecturer: 曾學文.
第六章 类的扩展与继承.
Java 程式設計 講師:FrankLin.
西南科技大学网络教育系列课程 高级语程序设计(Java) 第五章 继承、接口与范型.
第六章 继承性和派生类 胡昊 南京大学计算机系软件所.
程式設計實作.
Object-Oriented Programming:
類別樣板 Class Template 類似函式樣板 由類別樣板產生的類別稱為類別樣版的實體(instance)
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
Java软件设计基础 5. 继承与多态.
2 C++ 的基本語法和使用環境 親自撰寫和執行程式是學好程式語言的不二法門。本章藉由兩個簡單的程式,介紹C++ 程式的基本結構和開發環境,讓初學者能逐漸建立使用C++ 的信心。
第9章 類別圖與物件圖 9-1 類別圖與物件圖的基礎 9-2 類別圖的符號 9-3 類別關係 9-4 物件圖 9-5 繪製類別圖與物件圖
Java程序设计 第9章 继承和多态.
王豐緒 銘傳大學資訊工程學系 問題:JAVA 物件檔輸出入.
C#面向对象程序设计 $7 继承和多态性.
類別的繼承 Vehicle Car.
SPOTO TM JAVA课程 JAVA中的OO语法
中国矿大计算机学院杨东平 第5章 接口和包 中国矿大计算机学院杨东平
第9讲 Java的继承与多态(一) 类的继承 子类的创建 方法覆盖.
2019/1/16 Java语言程序设计-类与对象 教师:段鹏飞.
Php class 組員: 賴羿陵 林昱廷 莊正暉 張雅晴
Ch02-基礎語法.
C/C++/Java 哪些值不是头等程序对象
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
第六章 属性、索引器、委托和事件.
* 單元:電腦與問題解決 主題:Java物件導向程式設計-類別與物件 台南縣國立善化高中 蕭嘉民 老師
第16章 虛擬與多形 16-1 虛擬函數 16-2 純虛擬函數與抽象類別 16-3 多形 16-4 虛擬繼承與虛擬解構子.
第三章 C# 基础知识.
第7章 繼承/多型/介面 注意: 本投影片僅供本書上課教師使用,非經同意請勿上網轉載或供拷貝.
C#程序设计基础 $3 成员、变量和常量.
C++复习2----类与对象.
Java程式初體驗大綱 大綱 在學程式之前及本書常用名詞解釋 Hello Java!程式 在Dos下編譯、執行程式
Inheritance -II.
第三章 数据抽象.
C++语言程序设计教程 第2章 数据类型与表达式 第2章 数据类型与表达式 制作人:杨进才 沈显君.
第二章 Java语法基础.
面向对象技术 练习 ffh.
第五章 类图和对象图.
目标 流程控制 字符串处理 C# 的类和对象 C# 访问修饰符 C# 构造函数和析构函数.
#include <iostream.h>
第二章 Java基本语法 讲师:复凡.
方法進階及物件導向基礎 Lecturer: 楊昌樺.
第6單元 6-1 類別的繼承 (Class Inheritance) 6-2 抽象類別 (Abstract Class)
辅导课程十二.
JAVA 程式設計與資料結構 第三章 物件的設計.
第2章 Java语言基础.
對於成員(member)存取權的限制 成員的資料被毫無限制的存取,任誰都可以指定任意值給成員,Java語言為了防止這種現象的產生,規定:有一種成員的資料不能任由類別外部的任何人隨意存取。
辅导课程二.
資料結構與C++程式設計進階 C++與資料結構 講師:林業峻 CSIE, NTU 7/ 5, 2010.
第6章 继承和多态 伍孝金
Summary
Presentation transcript:

第15章 繼承與多重繼承 15-1 繼承的基礎 15-2 覆寫與隱藏父類別的成員 15-3 子類別的建構與解構子 15-4 多重繼承 15-5 軟體工程與繼承 15-6 類別的型態轉換與檢查

15-1 繼承的基礎 15-1-1 類別繼承的基礎 15-1-2 實作繼承 15-1-3 父類別的存取控制

15-1-1 類別繼承的基礎-圖例 「繼承」(Inheritance)是物件導向程式設計的一種進階觀念,繼承就是物件的再利用,當定義好一個類別後,其他類別可以繼承這個類別的成員資料和函數。 類別繼承也是在模擬真實世界,例如:學生和老師都是人,我們可以先定義Person類別來模擬人類,然後擴充Person類別建立Student類別來模擬學生,如右圖所示:

15-1-1 類別繼承的基礎-圖例說明 Person類別是Student類別的「父類別」(Superclass)或「基礎類別」(Base Class),反之Student類別是Person類別的「子類別」(Subclass)或「延伸類別」(Derived Class)。 UML類別圖的繼承是使用空心的箭頭線來標示兩個類別間的關係。

15-1-1 類別繼承的基礎-類別架構 繼承不只可以多個子類別繼承同一個父類別,還可以擁有很多層的繼承,如果將整個類別關聯性(Relationships)的樹狀結構都繪出來,稱為「類別架構」(Class Hierarchy),如下圖所示:

15-1-1 類別繼承的基礎-兄弟類別 Truck、Car和Motorcycle類別是「兄弟類別」(Sibling Classes),因為擁有相同Vehicle父類別。當然我們可以繼續繼承類別Car,類別SportsCar和Jeep也是類別Vehicle的子類別,不過並不是直接繼承的子類別。 簡單的說,Car類別是SportsCar和Jeep的直接父類別(Direct Base Class),Vehicle類別則是SportsCar和Jeep的間接父類別(Indirect Base Class)。

15-1-2 實作繼承-父類別的宣告 父類別vehicle定義車輛的基本資料,如下所示: class vehicle { private: int engineNo; string owner; public: void setNumber(int no) { engineNo = no; } void setOwner(string owner) { this->owner = owner; } void printVehicle() { } };

15-1-2 實作繼承-子類別的宣告 (語法) 類別如果是繼承自存在的其他類別,其宣告語法,如下所示: class 子類別名稱 : 存取修飾子 父類別名稱 { // 擴充的成員資料和函數 }; 上述類別宣告使用「:」運算子後跟著父類別,表示擴充父類別的宣告,在父類別前方的存取修飾子可以定義繼承父類別的存取範圍,其值可以是private、protected和public,詳細說明請參閱下一節。

15-1-2 實作繼承-子類別的宣告 (範例) 因為車輛可以分成很多種,例如:卡車、機車和轎車等,以轎車car子類別為例的類別宣告,如下所示: class car : public vehicle { private: int doors; public: car(string owner, int no, int doors) { } void printCar() { } };

15-1-2 實作繼承-UML類別圖 UML類別圖,如下圖所示:

15-1-2 實作繼承-繼承的成員種類 在C++語言宣告的子類別可以繼承父類別的所有成員資料和函數,但是並不包含: 父類別的建構子和解構子。 父類別的朋友關係。 父類別的指定運算子=。

15-1-3 父類別的存取控制-說明 在C++語言的子類別使用哪一種存取控制來繼承父類別,將影響成員的存取範圍,如下所示: 父類別名稱 { private: …… protected: public: }; class 子類別名稱 : 存取修飾子 父類別名稱 {

15-1-3 父類別的存取控制-父類別的存取控制 在子類別是使用存取修飾子private、protected和public來繼承父類別。父類別各種存取控制的說明,如下表所示:

15-1-3 父類別的存取控制-子類別的存取控制 子類別是否能夠存取父類別指定區塊的成員函數和資料,需視它屬於類別的public、protected和private成員而定,筆者整理如下表所示:

15-2 覆寫與隱藏父類別的成員 15-2-1 覆寫父類別的成員函數 15-2-2 隱藏父類別的成員資料

15-2-1 覆寫父類別的成員函數-說明 在父類別的成員函數如果不符合需求,子類別可以宣告同名、同參數列和傳回值的函數來取代父類別的成員函數,稱為「覆寫」(Override)。

15-2-1 覆寫父類別的成員函數-父類別 在父類別vehicle擁有一個靜態成員函數和成員函數需要覆寫,如下所示: class vehicle { private: ……… public: static void showBrand() { } void printVehicle(int index) { } }; 上述showBrand()和printVehicle()是需要覆寫的成員函數。

15-2-1 覆寫父類別的成員函數-子類別 子類別car使用public繼承父類別vehicle,如下所示: class car : public vehicle { private: ……… public: static void showBrand() { } void printVehicle(int no) { } }; 在程式碼呼叫car物件的成員函數時,就是呼叫子類別car的函數,而不是父類別的同名函數。

15-2-2 隱藏父類別的成員資料-說明 除了父類別的成員函數外,子類別也可以隱藏父類別成員資料的變數,只需變數名稱相同,就算變數型態不同也一樣可以隱藏。

15-2-2 隱藏父類別的成員資料-父類別 例如:父類別vehicle的成員變數owner是宣告在public區塊的string字串型態,如下所示: class vehicle { private: ……… public: string owner; };

15-2-2 隱藏父類別的成員資料-子類別 在子類別car使用public存取修飾子繼承父類別vehicle,如下所示: class car : public vehicle { private: int owner; ……… public: }; car物件的成員變數owner是整數int,不再是string字串,原來父類別public區塊的owner成員變數被隱藏起來。

15-3 子類別的建構與解構子 15-3-1 子類別的建構與解構順序 15-3-2 子類別傳遞參數給父類別

15-3-1 子類別的建構與解構順序 當建立子類別的物件呼叫子類別的建構子時,它會先初始化父類別的成員,也就是呼叫父類別的建構子。如果子類別沒有建構子,在建立物件時,預設建構子(Default Constructor)就會呼叫父類別的預設建構子。 簡單的說,在呼叫子類別的建構子前,會先呼叫父類別的建構子,而解構子剛好與建構子是相反順序,也就是子類別的建構子是在父類別的建構子之前呼叫。

15-3-2 子類別傳遞參數給父類別 當父類別擁有建構子時,在子類別可以傳遞參數給父類別的建構子。例如:car類別是繼承自vehicle,此時car子類別的建構子,如下所示: car(int owner, int no, int doors) : vehicle(owner, no) { this->doors = doors; } 上述建構子的「:」運算子後是傳遞給父類別vehicle建構子的參數,如果父類別不只一個,請使用「,」號分隔。 其中傳遞給父類別參數的值,就是傳入子類別建構子的參數值,以此例,owner和no也是子類別建構子的參數。

15-4 多重繼承-說明 「多重繼承」(Multiple Inheritance)是指一個類別能夠繼承多個父類別,如下圖所示:

15-4 多重繼承-語法 多重繼承。其宣告語法如下所示: class 子類別名稱 : 存取修飾子 父類別名稱, 存取修飾子 父類別名稱….. { …… // 額外的成員資料和函數 }; 上述類別和繼承類別的語法相似,因為繼承類別不只一個,需要使用「,」逗號來分隔。

15-4 多重繼承-範例 例如:繼承自truck和driver類別的子類別driven_tuck,如下所示: class driven_truck : public truck, public driver { public: driven_truck(float pl, float fl, float pay, int pd): truck(pl, fl), driver( pay, pd) { } float costPerTom( float cost_of_gas ) { } void printData() { } };

15-5 軟體工程與繼承-圖例 軟體工程的繼承是類別關聯性(Relationships),它是指不同類別間的關係。例如:繼承是Is-a類別關聯性,稱為一般關係(Gereralization)。成品和零件(Whole-Part)的類別關聯性,即Part-of和Has-a關係,如下圖所示:

15-5 軟體工程與繼承-圖例說明 Part-of和Has-a關係的說明,如下所示: Part-of關係:指此類別是其他類別的零件,以上圖為例Wheel車輪和Door車門是Car車類別的零件。 Has-a關係:相反於Part-of關係,Car類別Has-a擁有Wheel和Door類別。 在UML的上述關係稱為「聚合關係」(Aggregation),或是另一種更強調Whole-part關係稱為「組成關係」(Composition)。

15-6 類別的型態轉換與檢查-說明 在ANSI-C++定義reinterpret_cast、static_cast、dynamic_cast和const_cast四種新的型態轉換運算子,可以使用在類別型態的轉換,其基本語法如下所示: static_cast<類別*>(運算式); const_cast<類別*>(運算式); dynamic_cast<類別*>(運算式); reinterpret_cast<類別*>(運算式); ANSI-C++還定義全新typeid運算子,可以檢查指定運算式或類別的型態,其語法如下所示: typeid(運算式)

15-6 類別的型態轉換與檢查-static_cast運算子 C++的static_cast運算子可以將類別型態指標轉換成其他類別型態的指標,只需是編譯程式能夠自動轉型的型態迫換,都可以使用static_cast運算子來明確表示所需的型態轉換,如下所示: class A {}; class B: public A {}; A *a = new A; B *b = static_cast<B*>(a); 上述程式碼使用static_cast<B*>運算子,將父類別A物件指標a,型態轉換成子類別B的物件指標b。

15-6 類別的型態轉換與檢查-const_cast運算子 C++的const_cast運算子可以取消常數物件指標成為一般物件指標,如下所示: class C {}; const C *c1 = new C; C *c2 = const_cast<C*>(c1); 上述程式碼使用const_cast<C*>運算子,將常數物件指標c1型態轉換成非常數物件指標c2。

15-6 類別的型態轉換與檢查-dynamic_cast運算子 C++的dynamic_cast運算子主要是在類別架構中,安全的進行型態轉換,static_cast和dynamic_cast運算子的差異,在於dynamic_cast會進行檢查,這是在執行期檢查型態轉換的指標是否指向合法的需求型態,如果不是,就傳回NULL指標,如下所示: class D { virtual void dummy() {}; }; class E: public D {}; D *d1 = new E; D *d2 = new D; E *e1 = dynamic_cast<E*>(d1); E *e2 = dynamic_cast<E*>(d2); // 傳回NULL指標

15-6 類別的型態轉換與檢查-reinterpret_cast運算子 C++的reinterpret_cast運算子可以在完全無關的類別型態間進行轉換,其操作是二進位複製,從一個指標複製至另一個指標,如下所示: class F {}; class G {}; F *f = new F; G *g = reinterpret_cast<G*>(f); 上述程式碼使用reinterpret_cast<G*>運算子,將類別F物件指標f,型態轉換成類別G的物件指標g。

15-6 類別的型態轉換與檢查- typeid運算子 C++的typeid運算子可以在執行期傳回運算式的型態資訊,我們可以使用關係運算子「==」和「!=」來比較其傳回值,如下所示: class H {}; H *h1; H h2; if ( typeid(h1) != typeid(h2) ) { cout << "h1與h2型態不同\n"; } 上述程式碼使用typeid運算子檢查物件變數h2和物件指標變數h1是否是相同型態。