第八課_多態(tài)性_第1頁
第八課_多態(tài)性_第2頁
第八課_多態(tài)性_第3頁
第八課_多態(tài)性_第4頁
第八課_多態(tài)性_第5頁
已閱讀5頁,還剩48頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、第八課第八課 多態(tài)性多態(tài)性杜文峰杜文峰2021年年10月月17日日School of Information and Engineering, Shenzhen University2主要內(nèi)容主要內(nèi)容 多態(tài)性的基本概念概述 函數(shù)重載 運(yùn)算符重載 多態(tài)性的基本概念多態(tài)性的基本概念概述概述 School of Information and Engineering, Shenzhen University41. 什么叫多態(tài)性(什么叫多態(tài)性(Polymorphism)?)? 在程序中同一符號或名字在不同情況下具有不同解釋的現(xiàn)象稱為多態(tài)性。 現(xiàn)實(shí)世界中的多態(tài)現(xiàn)象 變色眼鏡:陽光下鏡片顏色變深;室內(nèi)鏡片

2、顏色變淺。 貓眼瞳孔:光線充足地方瞳孔變細(xì)變窄;晚上半夜瞳孔放大、夜視能力變強(qiáng)。 人的皮膚對溫度的反映:正常溫度正常接觸;遇上高溫緊急避險(xiǎn)。 C和C+中的除法運(yùn)算符“/”(用戶不用特別指名):當(dāng)兩個操作數(shù)都是整數(shù)時(shí),執(zhí)行整除功能;當(dāng)兩個操作數(shù)不全是整數(shù)時(shí),執(zhí)行浮點(diǎn)除功能。 School of Information and Engineering, Shenzhen University5面向?qū)ο蟪绦蛟O(shè)計(jì)中多態(tài)性的主要形式面向?qū)ο蟪绦蛟O(shè)計(jì)中多態(tài)性的主要形式 編譯時(shí)多態(tài) 指在編譯階段即可確定下來的多態(tài),主要通過重載機(jī)制獲得。 重載機(jī)制可分為函數(shù)重載和運(yùn)算符重載 函數(shù)重載:允許程序員用相同的名字定

3、義兩個或更多的C+函數(shù)(包括類中的成員函數(shù))、使得語義相近的函數(shù)可以用相同的標(biāo)識符來命名。 運(yùn)算符重載:允許程序員重新定義C+語言已有的運(yùn)算符,以一種更自然的方式使用程序員自己定義的類類型。School of Information and Engineering, Shenzhen University6例例 “”本來只能做整數(shù)和實(shí)數(shù)相加 通過重新定義,可以使“”除了可以執(zhí)行原來功能外,還可執(zhí)行復(fù)數(shù)相加,矩陣相加等;只要有必要,甚至可以重新定義使“”變成減運(yùn)算或除運(yùn)算等。School of Information and Engineering, Shenzhen University7 運(yùn)

4、行時(shí)多態(tài) 必須等到程序運(yùn)行時(shí)才可確定的多態(tài)性,主要是通過繼承結(jié)合動態(tài)綁定獲得。 要產(chǎn)生運(yùn)行時(shí)多態(tài)必須先設(shè)計(jì)一個類層次(繼承/派生),然后在某些類中使用虛函數(shù)。 虛函數(shù)和普通函數(shù)的區(qū)別: 普通函數(shù)采用靜態(tài)綁定;虛函數(shù)采用動態(tài)綁定。 (綁定實(shí)際上是代碼的連接。編譯時(shí)多態(tài)是靜態(tài)多態(tài)(靜態(tài)綁定);運(yùn)行時(shí)多態(tài)是動態(tài)多態(tài)(動態(tài)綁定)。 School of Information and Engineering, Shenzhen University8引入多態(tài)性的作用引入多態(tài)性的作用 為了獲得更靈活的表達(dá)方式,使程序的表示形式盡可能與所表示的內(nèi)容無關(guān)。 School of Information and

5、Engineering, Shenzhen University9概念分析概念分析 重載 重定義 重命名School of Information and Engineering, Shenzhen University10 重載 在聲明函數(shù)原型時(shí),函數(shù)形式參數(shù)的個數(shù)或者對應(yīng)位置的類型不同,兩個或更多的函數(shù)就可以共用同一個名字。這種在同一作用域中允許多個函數(shù)使用同一個函數(shù)名的措施被稱為重載(overloading); 如果在派生類中增加一個與基類成員函數(shù)同名的成員函數(shù),但函數(shù)的形式參數(shù)、類型或次序有所不同,這時(shí)編譯程序就認(rèn)為是增加了一個新的成員函數(shù),并不影響原有繼承成員函數(shù),這種情況稱為函數(shù)重

6、載。 School of Information and Engineering, Shenzhen University11 重定義 如果在派生類中定義了一個函數(shù)原型與繼承成員一摸一樣的成員函數(shù),則該成員函數(shù)的實(shí)現(xiàn)的函數(shù)體是對繼承成員函數(shù)的重定義。 繼承成員的重定義是在語義上重新修改繼承成員函數(shù)的實(shí)現(xiàn)。 School of Information and Engineering, Shenzhen University12 重命名 在派生類中不改變繼承成員的語義,僅僅為該成員起一個新名字。主要用它來解決名字沖突問題,以及允許派生類根據(jù)新的應(yīng)用環(huán)境選擇一個更合適的術(shù)語。School of In

7、formation and Engineering, Shenzhen University13函數(shù)重載函數(shù)重載 (overloading) 在聲明函數(shù)原型時(shí),形式參數(shù)個數(shù)或?qū)?yīng)位置的類型不同,兩個或更多的函數(shù)就可以共同用一個名字。這種在同一個作用域中允許多個函數(shù)使用同一個函數(shù)名的措施被稱為函數(shù)重載。 函數(shù)重載的一般形式 函數(shù)名相同,但函數(shù)原型不同,特別是形式參數(shù)個數(shù)或?qū)?yīng)位置的類型不同。 School of Information and Engineering, Shenzhen University14函數(shù)重載的例子函數(shù)重載的例子 在C語言中,求x的絕對值有兩個函數(shù): 當(dāng)x是整數(shù)時(shí)用 a

8、bs(x) 當(dāng)x是實(shí)數(shù)時(shí)用 fabs(x) 用戶在使用時(shí)必須根據(jù)x的所屬類型選擇相應(yīng)的函數(shù)。School of Information and Engineering, Shenzhen University15例例2 重載求絕對值函數(shù)重載求絕對值函數(shù)abs()() #include int abs(int x) return (x=0)?x:x); int abs(double x) return (x=0.0)?x:x); int abs(long x) return (x=0)?x:x); void main() coutabs(-5)”n”; /調(diào)用abs()整數(shù)版本 coutabs(

9、-5L)”n”; /調(diào)用abs()長整數(shù)版本 coutabs(3.14)”n”; /調(diào)用abs()雙精度浮點(diǎn)版本 School of Information and Engineering, Shenzhen University16例例3 關(guān)于關(guān)于add的重載的重載 void printadd(int a,int b) /兩個整數(shù)相加 couta”+”b”=”(a+b)endl; void printadd(char* a,char* b) /兩字符串相接 int L1,L2;char *p,*q,*t,*k; L1=strlen(a);L2=strlen(b); p=new charL1+

10、L2+1; k=p; q=a;t=b; while(*q!=0) *p=*q;p+;q+ while(*t!=0) *p=*t;p+;t+; *p=0; couta”+”b”=”; coutkb)?a:b); char* max(char* a,char* b) /求兩串中大者 char* max; max=(strcmp(a,b)0?a:b; return max; School of Information and Engineering, Shenzhen University18使用函數(shù)重載時(shí)必須注意的事項(xiàng)使用函數(shù)重載時(shí)必須注意的事項(xiàng) 不能通過函數(shù)類型(或者說函數(shù)返回值類型)來區(qū)別重載

11、函數(shù); 不能通過typedef來定義函數(shù)重載(因?yàn)閠ypedef只是定義類型別名,并非創(chuàng)建一個新的類型) 不能使用缺省參數(shù)形式來區(qū)分重載 不能通過參數(shù)不同傳遞方式來區(qū)分重載 School of Information and Engineering, Shenzhen University19例例include int func(int i) return i; int func(int i,int j=10;) /通過缺省參數(shù)形式來重載return (i*j); void main() coutfunc(3,4); coutfunc(5); /無法區(qū)分使用前一版本還是后一版本 School

12、of Information and Engineering, Shenzhen University20 例如 void func(int value); /無法區(qū)分 void func(int& value); 只能通過形式參數(shù)的區(qū)別來定義重載函數(shù)(通過形式參數(shù)個數(shù)或相應(yīng)位置類型不同) School of Information and Engineering, Shenzhen University21編譯程序?qū)χ剌d函數(shù)的匹配編譯程序?qū)χ剌d函數(shù)的匹配 函數(shù)調(diào)用的實(shí)際參數(shù)與一個重載函數(shù)的形式參數(shù)完全匹配(形參個數(shù)及其相應(yīng)位的類型),則選擇調(diào)用該重載函數(shù); 編譯程序找不到與實(shí)際參數(shù)(個數(shù)及相

13、應(yīng)位置類型)完全匹配的函數(shù)類型,但如果將一個類型隱式轉(zhuǎn)換為更高級類型后能找到完全匹配的函數(shù)原型,編譯程序?qū)⒄{(diào)用該重載函數(shù)。(注:類型轉(zhuǎn)換是隱型類型轉(zhuǎn)換,由C+編譯程序自動完成) School of Information and Engineering, Shenzhen University22函數(shù)重載的二義性函數(shù)重載的二義性 C+編譯程序無法在多個重載函數(shù)中選擇正確的函數(shù)進(jìn)行調(diào)用。 二義性錯誤是致命的,編譯程序?qū)o法生成目標(biāo)代碼。 二義性錯誤產(chǎn)生的主要原因?yàn)椋篊+語言的隱式類型轉(zhuǎn)換和缺省參數(shù)School of Information and Engineering, Shenzhen Un

14、iversity23 類型隱式轉(zhuǎn)換類型隱式轉(zhuǎn)換 由C+編譯程序自動完成。它把數(shù)值范圍較小的類型轉(zhuǎn)換為數(shù)值范圍較大的類型。 intunsigned intlongunsigned float 例子1 設(shè)定義了函數(shù)int func(double d); 在程序中使用coutfunc(A)時(shí)沒有任何問題,因?yàn)镃+編譯自動進(jìn)行了以下類型隱式轉(zhuǎn)換:charintfloatdouble 調(diào)用func(double)也沒有問題。School of Information and Engineering, Shenzhen University24 例子2 以下形式無法區(qū)分,出現(xiàn)二義性錯誤了#include

15、float abs(float x)return (x=0)?x:-x); double abs(double x)return (x=0)?x:-x); void main() coutabs(3.14)/n; /調(diào)用abs(double)版本 coutabs(-5)“/n”; /出現(xiàn)二義性,編譯無法確定采 用abs()哪個版本,因?yàn)榭梢杂衋bsfloat,也有absdouble School of Information and Engineering, Shenzhen University25使用缺省值參數(shù),也會造成重載二義性使用缺省值參數(shù),也會造成重載二義性 #include int

16、 func(int i)return i; int func(int i,int j=10)return i*j; void main() coutfunc(3,4)/n; /調(diào)用func(int,int) coutfunc(5)“/n”; /出現(xiàn)二義性,它不知道使用func(int)版本還是func(int,int)缺省參數(shù)版本School of Information and Engineering, Shenzhen University26函數(shù)重載的應(yīng)用函數(shù)重載的應(yīng)用構(gòu)造函數(shù)重載構(gòu)造函數(shù)重載 復(fù)習(xí):構(gòu)造函數(shù)功能和構(gòu)造函數(shù)定義基本形式 功能:創(chuàng)建對象時(shí)自動調(diào)用它為新創(chuàng)建的對象進(jìn)行初始化

17、基本形式:構(gòu)造函數(shù)名與類名相同,不能帶有函數(shù)類型 構(gòu)造函數(shù)定義時(shí)形式參數(shù)主要形式 構(gòu)造函數(shù)不帶參數(shù)采用某個默認(rèn)值作為參數(shù); 使用普通數(shù)值作為參數(shù)采用指定值為創(chuàng)建的對象初始化; 以一個已知的對象作為參數(shù)用一個已知對象為新創(chuàng)建對象進(jìn)行初始化。 School of Information and Engineering, Shenzhen University27練習(xí)練習(xí)運(yùn)算符重載運(yùn)算符重載 School of Information and Engineering, Shenzhen University29運(yùn)算符重載運(yùn)算符重載 為運(yùn)算符定義新的運(yùn)算功能,使它除具備有原來系統(tǒng)規(guī)定的功能外,還具備有

18、新定義的功能。 例如運(yùn)算符“”,原來規(guī)定它能進(jìn)行整數(shù)相加和實(shí)數(shù)相加功能,我們可以對它進(jìn)行重載,使它具有復(fù)數(shù)相加、矩陣相加等新功能。同時(shí)也可以重載,使它完成同一個類的對象相加等。 School of Information and Engineering, Shenzhen University30運(yùn)算符重載的實(shí)現(xiàn)運(yùn)算符重載的實(shí)現(xiàn) 通過運(yùn)算符函數(shù)來修改相應(yīng)的函數(shù)功能 一般函數(shù)的定義形式: 函數(shù)類型 函數(shù)名(形式參數(shù)表)函數(shù)體 函數(shù)類型是函數(shù)返回值所屬類型,函數(shù)名要符合用戶自定義標(biāo)識符要求,形式參數(shù)表是執(zhí)行函數(shù)時(shí)所需參數(shù)的說明,函數(shù)體是函數(shù)功能描述。School of Information an

19、d Engineering, Shenzhen University31 運(yùn)算符重載函數(shù)的定義形式為:函數(shù)類型 運(yùn)算符重載標(biāo)識 重載運(yùn)算符(形參表) 函數(shù)體 運(yùn)算符重載標(biāo)識是專門記號 重載運(yùn)算符表示重載哪一個運(yùn)算符School of Information and Engineering, Shenzhen University32操作符重載定義形式操作符重載定義形式函數(shù)類型 operator 運(yùn)算符(參數(shù)表)函數(shù)體 函數(shù)類型 類作用域:operator 運(yùn)算符(參數(shù)表)函數(shù)體 School of Information and Engineering, Shenzhen University

20、33重載運(yùn)算符函數(shù)作為類成員函數(shù)時(shí)重載運(yùn)算符函數(shù)作為類成員函數(shù)時(shí)關(guān)于參數(shù)個數(shù)的討論關(guān)于參數(shù)個數(shù)的討論 重載一元運(yùn)算符,不再顯式指明參數(shù);重載二元運(yùn)算符時(shí),只需顯式指明一個參數(shù);參數(shù)個數(shù)總是比實(shí)際參數(shù)個數(shù)少一個。 編譯程序處理成員函數(shù)時(shí),為它設(shè)置了一個this指針。在重載運(yùn)算符函數(shù)中,默認(rèn)this指針對應(yīng)的缺省參數(shù)就是其中之一個參數(shù),對于一元運(yùn)算符函數(shù)使用的就是規(guī)定的this指針?biāo)傅膮?shù)(自身的參數(shù)),對于二元運(yùn)算符對應(yīng)是二元運(yùn)算的左操作數(shù)。 School of Information and Engineering, Shenzhen University34例例 復(fù)數(shù)的和重載復(fù)數(shù)的和重載

21、復(fù)數(shù)類中重載“+”的函數(shù)體中: temp.real=real+other.real; temp.image=image+other.image; 相當(dāng)于: temp.real=thisreal+other.real; temp.image=thisimage+other.image; 重載二元運(yùn)算符時(shí)必須特別注意兩個操作數(shù)的左右位置,特別是重載減法運(yùn)算符: COMPLEX COMPLEX:operator -(const COMPLEX& other) COMPLEX temp; temp.real=real-other.real; /相當(dāng)于thisreal-other.real temp.i

22、mage=image-other.image; /相當(dāng)于thisimage-other.image return temp; School of Information and Engineering, Shenzhen University35 重載賦值運(yùn)算符“=” COMPLEX COMPLEX:operator =(const COMPLEX& other) real=other.real; /相當(dāng)于this.real=other.real image=other.image; /相當(dāng)于this.image=other.image return *this; 聲明一個對象時(shí)作初始化也采用

23、運(yùn)算符“=”,但此時(shí)采用的是拷貝構(gòu)造函數(shù)而不是調(diào)用重載賦值運(yùn)算符。School of Information and Engineering, Shenzhen University36 重載下標(biāo)運(yùn)算符“ ” 下標(biāo)運(yùn)算符“ ”用來數(shù)某個向量的某個元素,或直接對向量中某個元素賦值,它被視為一個二元運(yùn)算符。 下標(biāo)運(yùn)算符只能作類成員運(yùn)算符進(jìn)行重載,不可作為友元運(yùn)算符。 School of Information and Engineering, Shenzhen University37#include #include const int MAX_SIZE=10; class VECTOR pub

24、lic: VECTOR() /構(gòu)造函數(shù) int loop;for(loop=0;loop=MAX_SIZE-1; loop=loop+1) tableloop=loop; int& operator (int index) /取向量元素 if(indexMAX_SIZE-1) cout”Index out of bounds.n”; exit(1); return tableindex; protected: int tableMAX_SIZE; /向量的內(nèi)容 int main() VECTOR label; /定義向量對象 coutlabel2”n”; /輸出結(jié)果為2 babel2=8; /

25、改變第三個變量的值 coutlabel2”n”; /輸出結(jié)果為8 coutlabel10”n”; /引起程序異常終止,提示Index out of bounds return 0; 重載下標(biāo)運(yùn)算符的最大好處是提供一種向量訪問的安全方法。 School of Information and Engineering, Shenzhen University38友元友元 友元:允許類的設(shè)計(jì)者選擇出一組其他的類或函數(shù),使得它們可以訪問該類的私有成員和受保護(hù)成員。 C+的嚴(yán)格性和靈活性 嚴(yán)格性:強(qiáng)類型檢查、類的私有和受保護(hù)數(shù)據(jù)訪問的控制(類、封裝); 靈活性:提供友元,打破類型檢查的隱式和強(qiáng)制類型轉(zhuǎn)換,

26、打破訪問控制。School of Information and Engineering, Shenzhen University39 友元函數(shù)的定義形式 friend 函數(shù)類型 函數(shù)名(形式參數(shù)表); 友元運(yùn)算符重載定義形式: friend 函數(shù)類型 operator 運(yùn)算符(形式參數(shù)表); 不管友元函數(shù)或友元運(yùn)算符重載,都必須顯式地聲明其所有參數(shù),因?yàn)橛言瘮?shù)不是一個類的成員函數(shù),在友元函數(shù)體中不能使用this指針。School of Information and Engineering, Shenzhen University40如重載類如重載類INTEGER成員函數(shù)重載成員函數(shù)重載“

27、+”: INTEGER operator +(INTEGER other) /重載加法運(yùn)算符 INTEGER temp; temp.value=value+other.value; return temp; 此重載函數(shù)作為類成員函數(shù),默認(rèn)第一操作數(shù)是對象本身(使用了this指針),所以在使用時(shí),第一操作數(shù)必須是對象: void main() INTEGER x(10); /創(chuàng)建對象x,初始化value值為10; INTERGER y=x;/創(chuàng)建對象y,調(diào)用拷貝構(gòu)造函數(shù)初始化 INTERGER z; /創(chuàng)建對象z,用默認(rèn)缺省值初始化 y=x+10; /合理調(diào)用,因第一操作數(shù)為對象 z=30+y;

28、 /不合法,因第一操作數(shù)不是對象 return 0; School of Information and Engineering, Shenzhen University41改用友元重載加法運(yùn)算符改用友元重載加法運(yùn)算符 class INTEGER friend INTEGER operator +(INTERGER obj1,INTERGER obj2); . ; INTEGER operator +(INTERGER obj1,INTERGER obj2) INTEGER temp; temp.value=obj1.value+obj2.value; return temp; void ma

29、in() INTEGER x(10); INTERGER y=x; INTERGER z; y=x+2; /合法調(diào)用,相當(dāng)于y=x+INTEGER(2); z=30+y; /合法調(diào)用,相當(dāng)于z=INTEGER(30)+y; School of Information and Engineering, Shenzhen University42友元函數(shù)注意點(diǎn)友元函數(shù)注意點(diǎn) 友元函數(shù)不是類的成員函數(shù),在友元函數(shù)體中訪問對象的成員,必須用對象名加運(yùn)算符“.”加對象成員名。友元函數(shù)可以訪問類中的所有成員(公有的、私有的、保護(hù)的),一般函數(shù)只能訪問類中的公有成員; 友元函數(shù)不受類中的訪問權(quán)限關(guān)鍵字限制,

30、可以把它放在類的公有、私有、保護(hù)部分,結(jié)果一樣;School of Information and Engineering, Shenzhen University43 類的友元函數(shù)的作用域并非該類域。如果該友元函數(shù)是另一個類的成員函數(shù),則其作用域?yàn)榱硪活惖念愑?,否則與一般函數(shù)相同。 友元函數(shù)破壞了面向?qū)ο蟪绦蛟O(shè)計(jì)類的封裝性,所以友元函數(shù)如不是必須使用,則盡可能少用?;蛘哂闷渌侄伪WC封裝性。School of Information and Engineering, Shenzhen University44 友元還有友元類概念:整個類可以是另一個類的友元。友元類的每個成員函數(shù)都是另一個類的

31、友元函數(shù),都可訪問另一個類中的保護(hù)或私有數(shù)據(jù)成員。 class A friend class B; /聲明B為A的友元類 ;School of Information and Engineering, Shenzhen University45例例 賦值運(yùn)算符重載為成員函數(shù)賦值運(yùn)算符重載為成員函數(shù)#include class Location public: Location( )X = Y = 0; Location(int i, int j)X = i; Y = j; Location(A &p)X = p.X; Y = p.Y; Location & operator = (Locati

32、on &p); int getX( )return X; int getY( )return Y; private: int X, Y;School of Information and Engineering, Shenzhen University46Location& Location :operator = (Location &p) X = p.X; Y = p.Y; cout Assigment operator called.n; return *this;void main( ) Location a(7, 8); Location b; b = a; cout b.getX(

33、 ) , b.getY( ) endl;輸出:Assignment operator called.7, 8School of Information and Engineering, Shenzhen University47例例 重載增量運(yùn)算符重載增量運(yùn)算符#include class counter public: counter( )v = 0; counter operator +( ); counter operator +( int); void print( ) cout v endl; private: unsigned v;counter counter : operator +( ) v+; return *this;counter counter : operator +(int) counter t; t.v = v+; return t;void main( ) counter c; for(int i = 0; i 8; i+) c+; c.print( ); for(i = 0; i 8; i+) +c; c.print( );School of Information and Engineering, Shenzhen University48第二個參數(shù)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論