12 虛擬函數 12.1 多載與超載 12-2 多載函數 12-2 超載函數 12-4 12.2 虛擬函數 12-6 同名異式 12-7

Slides:



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

大葉大學 指導教授: 黃鈴玲 學生: 林慶南(工業工程與科技管理所)
計算機程式語言實習課.
四資二甲 第三週作業 物件導向程式設計.
第6章 多态性与虚函数.
第11章 過載與多形 11-1 方法的過載 11-2 運算子的過載 11-3 再談抽象類別與介面 11-4 多形的基礎 11-5 實作多形.
06 類別與物件. 06 類別與物件 6.1 類別與物件 目前的程式設計主流是物件導向 (OOP),Visual C# 已提供完整的物件導向功能。在物件導向設計裡,物件可以被封裝 ( 保護) 和繼承 ( 重複使用)。因為物件的封裝會使物件受到保護,要存取物件必須透過屬性 (Property)、方法.
11 繼承類別 11.4 建立者與破壞者 單一建立者與破壞者 11-20
類別與物件 Class & Object.
Virtual Function Jing(井民全).
C++入門 以Dev C++為例.
第十一章 繼承類別和朋友關係.
挑戰C++程式語言 ─第13章 運算子的覆載.
Chapter 5 遞迴 資料結構導論 - C語言實作.
刘胥影 东南大学计算机学院 面向对象程序设计1 2010~2011第3学期 刘胥影 东南大学计算机学院.
程式語言的基礎 Input Output Program 世代 程式語言 第一世代 Machine language 第二世代
Java簡介.
Visual C++ introduction
簡易C++除錯技巧 長庚大學機械系
Derived Class 前言 衍生類別的定義 單一繼承 public, protected, 和 privated 基底類別
2 C++ 程式概論 2.1 C++ 程式結構 程式註解 // 插入標題檔 #include 2-3
101北一女中 資訊選手培訓營 妳不可不了解的指標 Nan.
西安交通大学 计算机教学实验中心 大学C++程序设计教程 西安交通大学 计算机教学实验中心
C語言簡介 日期 : 2018/12/2.
類別(class) 類別class與物件object.
SQL Stored Procedure SQL 預存程序.
程式設計(二) 進階類別 郭文真 Sabrina Kuo.
Object-Oriented Programming: Polymorphism
中国矿大计算机学院杨东平 第5章 接口和包 中国矿大计算机学院杨东平
第四章 小技巧.
繼承概念的優點 類別再使用(程式碼再使用) 抽象化概念再使用 類別關係階層化.
Java 程式設計 講師:FrankLin.
JAVA 程式設計與資料結構 第四章 陣列、字串與數學物件.
Instructor Textbook Requirements TAs C++程式設計風格與藝術 (O’Reilly).
C/C++/Java 哪些值不是头等程序对象
Topic Introduction—RMI
第一單元 建立java 程式.
第16章 虛擬與多形 16-1 虛擬函數 16-2 純虛擬函數與抽象類別 16-3 多形 16-4 虛擬繼承與虛擬解構子.
第7章 繼承/多型/介面 注意: 本投影片僅供本書上課教師使用,非經同意請勿上網轉載或供拷貝.
第 19 章 XML記憶體執行模式.
|07 函數.
第十章 指標.
物件導向程式設計 參考書目: 1. 洪維恩,C++ 教學手冊 第三版,旗標出版圖書公司。 2. 陳錦揮,Java 初學指引,博碩文化 3
LINQ資料查詢技術.
Class & Object 靜宜大學資工系 蔡奇偉副教授 ©2011.
Inheritance -II.
樣版.
第三章 数据抽象.
函數 博碩文化出版發行.
C qsort.
C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计.
繼承的優點 程式碼再使用 (code reuse) 抽象概念再使用 類別階層化 澄清物件間的關係.
OOP9 類別Class.
第九章 物件導向-進階.
陣列與結構.
北一女中 資訊選手培訓營 妳不可不了解的指標 Nan.
進階UI元件:ListView元件以及複選 靜宜大學資管系 楊子青
第一讲 面向对象方法学与信息系统建模.
谭浩强编著 C++面向对象程序设计 授课教师:姬广永 学习网站:
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
《数据结构与算法设计》第一部分 面向对象的C++程序设计基础.
第四章 陣列、指標與參考 4-1 物件陣列 4-2 使用物件指標 4-3 this指標 4-4 new 與 delete
What is “this”? 在物件導向程式設計中,類別的定義就是在說明如果創建了“這個物件”的話,它會具有那些屬性與功能,以及這些功能是如何實現的。 而所謂的“這個物件”就以 this 來表示。 當我們在JavaScript與jQuery中寫 script 程式(函式)時,“誰”呼叫這個函式,這個“誰”就是該函式中所謂的.
Object-Oriented Programming
Introduction to the C Programming Language
String類別 在C語言中提供兩種支援字串的方式 可以使用傳統以null結尾的字元陣列 使用string類別
13 繼承類別 13.1 繼承概論 基礎類別與衍生類別 繼承型式 13-2
第6章 继承和多态 伍孝金
方法(Method) 函數.
InputStreamReader Console Scanner
Presentation transcript:

12 虛擬函數 12.1 多載與超載 12-2 12.1.1 多載函數 12-2 12.1.2 超載函數 12-4 12 虛擬函數 12.1 多載與超載 12-2 12.1.1 多載函數 12-2 12.1.2 超載函數 12-4 12.2 虛擬函數 12-6 12.2.1 同名異式 12-7 12.2.2 虛擬函數 12-9 12.2.3 基礎類別指標 12-11 12.2.4 虛擬物件指標 12-13 12.3 抽象類別 12-15 12.3.1 虛擬類別繼承 12-15 12.3.2 純虛擬函數 12-18 12.3.3 抽象基礎類別 12-19

12.1 多載與超載 多載(overloading)是在同一類別中,重複定義二個或多個名稱相同,但參數各數不同或參數型態不同的函數。 12.1 多載與超載 多載(overloading)是在同一類別中,重複定義二個或多個名稱相同,但參數各數不同或參數型態不同的函數。 超載(overriding)則是在衍生類別中,重新定義一個與基礎類別名稱相同,但參數個數或參數型態可能相同也可能不同的函數。

12.1 多載與超載 (續) 呼叫同一個類別的多載函數時,可以因不同的參數個數或不同的參數型態,而自動執行對應的多載函數。 12.1 多載與超載 (續) 呼叫同一個類別的多載函數時,可以因不同的參數個數或不同的參數型態,而自動執行對應的多載函數。 可是呼叫基礎類別或衍生類別的多載函數時,卻不會自動執行對應的多載函數,而必須使用範圍運算符號加以限制呼叫的範圍。因此,這種多載函數(overloading function)實際只是超載函數(overriding function)的功能。

12.1.1 多載函數 建立Base類別 class Base //宣告基礎類別 { public: 12.1.1 多載函數 建立Base類別 class Base //宣告基礎類別 { public: void show(char str1[], char str2[]) { cout << str1 << '\t' << str2 << endl; } };

12.1.1 多載函數 (續) 建立Derived類別以public型態繼承Base類別 12.1.1 多載函數 (續) 建立Derived類別以public型態繼承Base類別 class Derived: public Base //宣告衍生類別 { public: void show(char str3[]) { //衍生類別多載方法 cout << str3 << endl; } };

12.1.1 多載函數 (續) 建立Derived物件d並呼叫Derived類別的show函數 int main() { 12.1.1 多載函數 (續) 建立Derived物件d並呼叫Derived類別的show函數 int main() { Derived d; //建立Derived物件d char s1[] = "基礎參數1"; //定義並起始s1字串 char s2[] = “基礎參數2”; //定義並起始s2字串 char s3[] = "衍生參數"; //定義並起始s3字串 d.show(s1, s2); //呼叫Derived多載方法錯誤 d.Base::show(s1, s2); //呼叫Base方法 d.show(s3); //呼叫Derived多載方法 return 0; //正常結束程式 }

12.1.2 超載函數 建立Base類別 class Base //宣告基礎類別 { public: 12.1.2 超載函數 建立Base類別 class Base //宣告基礎類別 { public: void show() { //基礎類別方法 cout << "基礎類別show函數" << endl; } };

12.1.2 超載函數 (續) 建立Derived類別 class Derived: public Base //宣告衍生類別 { 12.1.2 超載函數 (續) 建立Derived類別 class Derived: public Base //宣告衍生類別 { public: void show() { //衍生類別多載方法 Base::show(); //呼叫基礎類別show函數 cout << "衍生類別show函數" << endl; } };

12.1.2 超載函數 (續) 建立Derived物件d,並呼叫Derived類別的show函數 int main() { 12.1.2 超載函數 (續) 建立Derived物件d,並呼叫Derived類別的show函數 int main() { Derived d; //建立Derived物件d d.show(); //呼叫Derived多載方法 return 0; //正常結束程式 }

12.2 虛擬函數 一般而言,C++ 在編譯過程會自動將同一類別的函數結合在一起(稱為靜態結合),因此當衍生類別含有基礎類別的超載函數,則執行時將自動呼叫同一類別的同名異式函數。 例如若此呼叫發生在基礎類別,則被呼叫的是基礎類別的同名異式函數;若此呼叫發生在衍生類別,則被呼叫的是衍生類別的同名異式函數。

12.2 虛擬函數 (續) 若以virtual宣告同名異式的函數,則C++ 在編譯過程會建立一個虛擬函數表(virtual function table),供執行時將同一物件的函數結合在一起(稱為動態結合),因此當執行時呼叫繼承體系中的同名異式,將呼叫物件所屬類別的同名異式函數。 例如若執行呼叫的是以基礎類別建立的物件,則被呼叫的是基礎類別的同名異式函數,若執行呼叫的是以衍生類別建立的物件,則被呼叫的是衍生類別的同名異式函數。

12.2.1 同名異式 同名異式(polymorphism)是在基礎類別與衍生類別中多載相同名稱但不同功能的public成員函數,且類別體系中的某個函數呼叫此同名的多載函數,因此當類別物件呼叫此函數時,此函數將呼叫同一類別的多載函數。 發生這種情形是因C++ 編譯器在類別成員函數呼叫時執行靜態結合,所謂靜態結合(static binding)又稱前期結合(early binding)表示C++ 在編譯過程自動結合同一類別的函數呼叫。

12.2.1 同名異式 (續)

12.2.2 虛擬函數 若將此同名異式的成員宣告為virtual函數,則編譯時C++ 會給予此同名異式函數不同的指標,因此執行時會依據類別指標存取適當的函數。 這種情形是因C++ 編譯器對virtual函數執行動態結合,所謂動態結合(dynamic binding)又稱為後期結合(late binding)是C++ 在執行過程自動結合同一物件的函數呼叫。

12.2.2 虛擬函數 (續)

12.2.3 基礎類別指標 如果將基礎類別物件的位址或是衍生類別物件的位址存入基礎類別物件的指標中,然後以此指標呼叫同名異式的函數時,則此指標都指向基礎類別,而且都是呼叫基礎類別的同名函數。

12.2.3 基礎類別指標 (續) 建立Base類別,再建立Derived類別 class Base { public: 12.2.3 基礎類別指標 (續) 建立Base類別,再建立Derived類別 class Base { public: void show() {cout << "基礎類別\n";} //宣告Base::show() }; class Derived: public Base { void show() {cout << "衍生類別\n";} //宣告Derived::show()

12.2.3 基礎類別指標 (續) 建立Base物件b與Derived物件d,然後以b或d物件呼叫show函數 int main() { 12.2.3 基礎類別指標 (續) 建立Base物件b與Derived物件d,然後以b或d物件呼叫show函數 int main() { Base *ptr; Base b; Derived d; ptr = &b; //ptr指向物件b位址 ptr->show(); //顯示"基礎類別" ptr = &d; //ptr指向物件d位址 return 0; }

12.2.4 虛擬物件指標 若將此同名異式的成員宣告為virtual函數,則編譯時C++ 會給予此同名異式函數不同的指標,因此執行時會依據物件指標存取適當的函數。

12.2.4 虛擬物件指標 (續) 建立Base類別,再建立Derived類別 class Base { public: 12.2.4 虛擬物件指標 (續) 建立Base類別,再建立Derived類別 class Base { public: virtual void show() {cout << “基礎類別\n”;} //宣告Base::show() }; class Derived: public Base { virtual void show() {cout << "衍生類別\n";} //宣告Derived::show()

12.2.4 虛擬物件指標 (續) 建立Base物件b與Derived物件d,然後以b與d物件呼叫show函數 int main() { 12.2.4 虛擬物件指標 (續) 建立Base物件b與Derived物件d,然後以b與d物件呼叫show函數 int main() { Base *ptr; Base b; Derived d; ptr = &b; //ptr指向物件b位址 ptr->show(); //顯示"基礎類別" ptr = &d; //ptr指向物件d位址 return 0; }

12.3 抽象類別 抽象類別是在基礎類別中宣告純虛擬函數,也就是宣告函數的原型,並令該函數原型等於0,而不定義該函數的功能。 12.3 抽象類別 抽象類別是在基礎類別中宣告純虛擬函數,也就是宣告函數的原型,並令該函數原型等於0,而不定義該函數的功能。 然後衍生類別必須在類別中實現純虛擬函數的功能。這相當於在基礎類別中保留一個存取基礎類別成員的介面,但讓衍生類別去實現此介面的功能。

12.3.1 虛擬類別繼承 如下圖,若衍生類別1與衍生類別2繼承基礎類別時,沒有宣告為虛擬(virtual)繼承,則C++ 將配置二個不同位址給衍生類別1與衍生類別2的基礎類別,所以衍生類別3存取基礎類別的成員時,C++ 無法確定其路徑為「基礎類別─衍生類別1─衍生類別3」或「基礎類別─衍生類別2─衍生類別3」?因此編譯時將出現ambiguous(模擬兩可)的錯誤訊息。

12.3.1 虛擬類別繼承 (續)

12.3.1 虛擬類別繼承 (續) 範例 class Base { public: int i; }; 12.3.1 虛擬類別繼承 (續) 範例 class Base { public: int i; }; class Derived1: virtual public Base int j;

12.3.1 虛擬類別繼承 (續) 範例續 class Derived2: virtual public Base { public: 12.3.1 虛擬類別繼承 (續) 範例續 class Derived2: virtual public Base { public: int k; }; class Derived3: public Derived1, public Derived2 int sum = i + j + k;

12.3.1 虛擬類別繼承 (續) 範例續 void main() { Derived3 d3; //建立Derived3物件d3 12.3.1 虛擬類別繼承 (續) 範例續 void main() { Derived3 d3; //建立Derived3物件d3 d3.i = 10; //設定Base資料成員 d3.j = 20; //設定Derived1資料成員 d3.k = 30; //設定Derived2資料成員 Derived2 d2; //建立Derived2物件d2 d2.i = 15; //設定Base資料成員 d2.k = 45; //設定Derived2資料成員 }

12.3.2 純虛擬函數 virtual 傳回型態 函數名稱(參數列) = 0; 12.3.2 純虛擬函數 virtual 傳回型態 函數名稱(參數列) = 0; 存虛擬函數(pure virtual function)只宣告函數並且令虛擬函數等於0,但未定義虛擬函數的本體。

12.3.3 抽象基礎類別 抽象類別(abstract class)是包含一個或多個純虛擬成員函數的類別。因此,若衍生類別繼承了抽象類別後,必須在衍生類別中超載(override)與實現(implements)純虛擬函數。 範例 class Base { public: virtual void show() = 0; //show()為虛擬函數 };

12.3.3 抽象基礎類別 (續) 範例續 class Derived1: public Base { public: 12.3.3 抽象基礎類別 (續) 範例續 class Derived1: public Base { public: void show() {cout << "衍生類別1\n";}//宣告Derived1::show() }; class Derived2: public Base { void show() {cout << "衍生類別2\n";}//宣告Derived2::show()

12.3.3 抽象基礎類別 (續) 範例續 void main() { Base *list[2]; Derived1 d1; 12.3.3 抽象基礎類別 (續) 範例續 void main() { Base *list[2]; Derived1 d1; Derived2 d2; list[0] = &d1; //指標[0]指向d1 list[1] = &d2; //指標[1]指向d2 list[0]->show(); //顯示"衍生類別1" list[1]->show(); //顯示"衍生類別2" }