C清華大學(xué)出版社第四版課件第八章.ppt
《C清華大學(xué)出版社第四版課件第八章.ppt》由會員分享,可在線閱讀,更多相關(guān)《C清華大學(xué)出版社第四版課件第八章.ppt(54頁珍藏版)》請在裝配圖網(wǎng)上搜索。
1 第八章多態(tài)性 東華理工大學(xué)信息工程學(xué)院 C 語言程序設(shè)計 2 本章主要內(nèi)容 多態(tài)性運算符重載虛函數(shù)純虛函數(shù)抽象類深度探索 3 多態(tài)性的概念 多態(tài)性是面向?qū)ο蟪绦蛟O(shè)計的重要特征之一 多態(tài)性是指發(fā)出同樣的消息被不同類型的對象接收時有可能導(dǎo)致完全不同的行為 多態(tài)的實現(xiàn) 函數(shù)重載運算符重載虛函數(shù) 4 問題舉例 復(fù)數(shù)的運算 classComplex 復(fù)數(shù)類聲明public Complex doubler 0 0 doublei 0 0 real r imag i voiddisplay const 顯示復(fù)數(shù)的值private doublereal doubleimag 運算符重載 5 問題舉例 復(fù)數(shù)的運算 用 能夠?qū)崿F(xiàn)復(fù)數(shù)的加減運算嗎 實現(xiàn)復(fù)數(shù)加減運算的方法 重載 運算符 運算符重載 6 運算符重載的實質(zhì) 運算符重載是對已有的運算符賦予多重含義必要性C 中預(yù)定義的運算符其運算對象只能是基本數(shù)據(jù)類型 而不適用于用戶自定義類型 如類 實現(xiàn)機(jī)制將指定的運算表達(dá)式轉(zhuǎn)化為對運算符函數(shù)的調(diào)用 運算對象轉(zhuǎn)化為運算符函數(shù)的實參 編譯系統(tǒng)對重載運算符的選擇 遵循函數(shù)重載的選擇原則 運算符重載 7 運算符重載 規(guī)則和限制 可以重載C 中除下列運算符外的所有運算符 只能重載C 語言中已有的運算符 不可臆造新的 不改變原運算符的優(yōu)先級和結(jié)合性 不能改變操作數(shù)個數(shù) 經(jīng)重載的運算符 其操作數(shù)中至少應(yīng)該有一個是自定義類型 8 兩種形式 重載為類的非靜態(tài)成員函數(shù)重載為非成員函數(shù) 運算符重載 9 運算符函數(shù) 聲明形式函數(shù)類型operator運算符 形參 重載為類成員函數(shù)時參數(shù)個數(shù) 原操作數(shù)個數(shù) 1 后置 除外 重載為非成員函數(shù)時參數(shù)個數(shù) 原操作數(shù)個數(shù) 且至少應(yīng)該有一個自定義類型的形參 運算符重載 10 運算符成員函數(shù)的設(shè)計 雙目運算符B如果要重載B為類成員函數(shù) 使之能夠?qū)崿F(xiàn)表達(dá)式oprd1Boprd2 其中oprd1為A類對象 則B應(yīng)被重載為A類的成員函數(shù) 形參類型應(yīng)該是oprd2所屬的類型 經(jīng)重載后 表達(dá)式oprd1Boprd2相當(dāng)于oprd1 operatorB oprd2 運算符重載 11 運算符重載 例8 1 將 運算重載為復(fù)數(shù)類的成員函數(shù) 規(guī)則 實部和虛部分別相加減 操作數(shù) 兩個操作數(shù)都是復(fù)數(shù)類的對象 includeusingnamespacestd classComplex 復(fù)數(shù)類定義public 外部接口Complex doubler 0 0 doublei 0 0 real r imag i 構(gòu)造函數(shù)Complexoperator constComplex 12 ComplexComplex operator constComplex 創(chuàng)建一個臨時無名對象作為返回值 13 voidComplex display const cout real imag endl intmain 主函數(shù)Complexc1 5 4 c2 2 10 c3 定義復(fù)數(shù)類的對象cout c1 c1 display cout c2 c2 display c3 c1 c2 使用重載運算符完成復(fù)數(shù)減法cout c3 c1 c2 c3 display c3 c1 c2 使用重載運算符完成復(fù)數(shù)加法cout c3 c1 c2 c3 display return0 14 程序輸出的結(jié)果為 c1 5 4 c2 2 10 c3 c1 c2 3 6 c3 c1 c2 7 14 15 16 運算符成員函數(shù)的設(shè)計 前置單目運算符U如果要重載U為類成員函數(shù) 使之能夠?qū)崿F(xiàn)表達(dá)式Uoprd 其中oprd為A類對象 則U應(yīng)被重載為A類的成員函數(shù) 無形參 經(jīng)重載后 表達(dá)式Uoprd相當(dāng)于oprd operatorU 運算符重載 17 運算符成員函數(shù)的設(shè)計 后置單目運算符 和 如果要重載 或 為類成員函數(shù) 使之能夠?qū)崿F(xiàn)表達(dá)式oprd 或oprd 其中oprd為A類對象 則 或 應(yīng)被重載為A類的成員函數(shù) 且具有一個int類型形參 經(jīng)重載后 表達(dá)式oprd 相當(dāng)于oprd operator 0 運算符重載 18 例8 2 運算符前置 和后置 重載為時鐘類的成員函數(shù) 前置單目運算符 重載函數(shù)沒有形參 對于后置單目運算符 重載函數(shù)需要有一個整型形參 操作數(shù)是時鐘類的對象 實現(xiàn)時間增加1秒鐘 運算符重載 includeusingnamespacestd classClock 時鐘類聲明定義public 外部接口Clock inthour 0 intminute 0 intsecond 0 voidshowTime const Clock 19 前置單目運算符重載函數(shù)Clock 20 后置單目運算符重載ClockClock operator int 注意形參表中的整型參數(shù)Clockold this this 調(diào)用前置 運算符returnold 21 其它成員函數(shù)的實現(xiàn)略intmain ClockmyClock 23 59 59 cout Firsttimeoutput myClock showTime cout ShowmyClock myClock showTime cout Show myClock myClock showTime return0 22 程序運行結(jié)果為 Firsttimeoutput 23 59 59ShowmyClock 23 59 59Show myClock 0 0 1 23 24 運算符非成員函數(shù)的設(shè)計 函數(shù)的形參代表依自左至右次序排列的各操作數(shù) 后置單目運算符 和 的重載函數(shù) 形參列表中要增加一個int 但不必寫形參名 如果在運算符的重載函數(shù)中需要操作某類對象的私有成員 可以將此函數(shù)聲明為該類的友元 運算符重載 25 運算符非成員函數(shù)的設(shè)計 雙目運算符B重載后 表達(dá)式oprd1Boprd2等同于operatorB oprd1 oprd2 前置單目運算符B重載后 表達(dá)式Boprd等同于operatorB oprd 后置單目運算符 和 重載后 表達(dá)式oprdB等同于operatorB oprd 0 運算符重載 26 例8 3 將 雙目 重載為非成員函數(shù) 并將其聲明為復(fù)數(shù)類的友元 兩個操作數(shù)都是復(fù)數(shù)類的常引用 將 雙目 重載為非成員函數(shù) 并將其聲明為復(fù)數(shù)類的友元 它的左操作數(shù)是std ostream引用 右操作數(shù)為復(fù)數(shù)類的常引用 返回std ostream引用 用以支持下面形式的輸出 cout a b 該輸出調(diào)用的是 operator operator cout a b 運算符重載 includeusingnamespacestd classComplex 復(fù)數(shù)類定義public 外部接口Complex doubler 0 0 doublei 0 0 real r imag i 構(gòu)造函數(shù)friendComplexoperator constComplex 27 Complexoperator constComplex 28 29 靜態(tài)綁定與動態(tài)綁定 綁定程序自身彼此關(guān)聯(lián)的過程 確定程序中的操作調(diào)用與執(zhí)行該操作的代碼間的關(guān)系 靜態(tài)綁定綁定過程出現(xiàn)在編譯階段 用對象名或者類名來限定要調(diào)用的函數(shù) 動態(tài)綁定綁定過程工作在程序運行時執(zhí)行 在程序運行時才確定將要調(diào)用的函數(shù) includeusingnamespacestd classPoint public Point doublex doubley x x y y doublearea const return0 0 private doublex y classRectangle publicPoint public Rectangle doublex doubley doublew doubleh doublearea const returnw h private doublew h 靜態(tài)綁定例 30 Rectangle Rectangle doublex doubley doublew doubleh Point x y w w h h voidfun constPoint 運行結(jié)果 Area 0 31 includeusingnamespacestd classPoint public Point doublex doubley x x y y virtualdoublearea const return0 0 private doublex y classRectangle publicPoint public Rectangle doublex doubley doublew doubleh virtualdoublearea const returnw h private doublew h 其他函數(shù)同上例 動態(tài)綁定例 32 voidfun constPoint 運行結(jié)果 Area 375 33 34 虛函數(shù) 虛函數(shù)是動態(tài)綁定的基礎(chǔ) 是非靜態(tài)的成員函數(shù) 在類的聲明中 在函數(shù)原型之前寫virtual virtual只用來說明類聲明中的原型 不能用在函數(shù)實現(xiàn)時 具有繼承性 基類中聲明了虛函數(shù) 派生類中無論是否說明 同原型函數(shù)都自動為虛函數(shù) 本質(zhì) 不是重載聲明而是覆蓋 調(diào)用方式 通過基類指針或引用 執(zhí)行時會根據(jù)指針指向的對象的類 決定調(diào)用哪個函數(shù) 虛函數(shù) 35 例8 4 includeusingnamespacestd classBase1 基類Base1定義public virtualvoiddisplay const 虛函數(shù) voidBase1 display const cout Base1 display endl classBase2 publicBase1 公有派生類Base2定義public voiddisplay const 覆蓋基類的虛函數(shù) voidBase2 display const cout Base2 display endl 虛函數(shù) 公有派生類Derived定義classDerived publicBase2 public voiddisplay const 覆蓋基類的虛函數(shù) voidDerived display const coutdisplay 對象指針 成員名 36 intmain 主函數(shù)Base1base1 定義Base1類對象Base2base2 定義Base2類對象Derivedderived 定義Derived類對象fun 運行結(jié)果 Base1 display Base2 display Derived display 37 38 虛析構(gòu)函數(shù) 為什么需要虛析構(gòu)函數(shù) 可能通過基類指針刪除派生類對象 如果你打算允許其他人通過基類指針調(diào)用對象的析構(gòu)函數(shù) 通過delete這樣做是正常的 就需要讓基類的析構(gòu)函數(shù)成為虛函數(shù) 否則執(zhí)行delete的結(jié)果是不確定的 虛函數(shù) 39 抽象類 帶有純虛函數(shù)的類稱為抽象類 class類名 virtual類型函數(shù)名 參數(shù)表 0 純虛函數(shù) 純虛函數(shù)與抽象類 40 抽象類 純虛函數(shù)與抽象類 作用抽象類為抽象和設(shè)計的目的而聲明 將有關(guān)的數(shù)據(jù)和行為組織在一個繼承層次結(jié)構(gòu)中 保證派生類具有要求的行為 對于暫時無法實現(xiàn)的函數(shù) 可以聲明為純虛函數(shù) 留給派生類去實現(xiàn) 注意抽象類只能作為基類來使用 不能聲明抽象類的對象 構(gòu)造函數(shù)不能是虛函數(shù) 析構(gòu)函數(shù)可以是虛函數(shù) 41 例8 5 純虛函數(shù)與抽象類 includeusingnamespacestd classBase1 基類Base1定義public virtualvoiddisplay const 0 純虛函數(shù) classBase2 publicBase1 公有派生類Base2定義public voiddisplay const 覆蓋基類的虛函數(shù)cout Base2 display endl classDerived publicBase2 公有派生類Derived定義public voiddisplay const 覆蓋基類的虛函數(shù)cout Derived display endl voidfun Base1 ptr ptr display 對象指針 成員名 intmain 主函數(shù)Base2base2 定義Base2類對象Derivedderived 定義Derived類對象fun 運行結(jié)果 Base2 display Derived display 42 多態(tài)類型與非多態(tài)類型 多態(tài)類型與非多態(tài)類型有虛函數(shù)的類類型稱為多態(tài)類型其它類型皆為非多態(tài)類型二者的差異語言層面的差異多態(tài)類型支持運行時類型識別多態(tài)類型對象占用額外的空間設(shè)計原則上的差異 43 深度探索 設(shè)計原則 多態(tài)類型多態(tài)類型的析構(gòu)函數(shù)一般應(yīng)為虛函數(shù)非多態(tài)類型非多態(tài)類型不宜作為公共基類由于沒有利用動態(tài)多態(tài)性 一般可以用組合 而無需用共有繼承 如果繼承 則由于析構(gòu)函數(shù)不是虛函數(shù) 刪除對象時所執(zhí)行操作與指針類型有關(guān) 易引起混亂 把不需被繼承的類型設(shè)定為非多態(tài)類型由于成員函數(shù)都是靜態(tài)綁定 調(diào)用速度較快 對象占用空間較小 44 深度探索 運行時類型識別 運行時類型識別允許在運行時通過基類指針 或引用 辨別對象所屬的具體派生類 只對多態(tài)類型適用 比虛函數(shù)動態(tài)綁定的開銷更大 因此應(yīng)僅對虛函數(shù)無法解決的問題使用 運行時類型識別的方式用dynamic cast做類型轉(zhuǎn)換的嘗試 用typeid直接獲取類型信息 45 深度探索 dynamic cast的使用 語法形式dynamic cast 表達(dá)式 功能將基類指針轉(zhuǎn)換為派生類指針 將基類引用轉(zhuǎn)換為派生類引用 轉(zhuǎn)換是有條件的如果指針 或引用 所指對象的實際類型與轉(zhuǎn)換的目的類型兼容 則轉(zhuǎn)換成功進(jìn)行 否則如執(zhí)行的是指針類型的轉(zhuǎn)換 則得到空指針 如執(zhí)行的是引用類型的轉(zhuǎn)換 則拋出異常 46 深度探索 例8 9dynamic cast示例 includeusingnamespacestd classBase public virtualvoidfun1 cout Base fun1 endl virtual Base classDerived1 publicBase public virtualvoidfun1 cout Derived1 fun1 endl virtualvoidfun2 cout Derived1 fun2 endl classDerived2 publicDerived1 public virtualvoidfun1 cout Derived2 fun1 endl virtualvoidfun2 cout Derived2 fun2 endl 47 深度探索 voidfun Base b b fun1 嘗試將b轉(zhuǎn)換為Derived1指針Derived1 d dynamic cast b 判斷轉(zhuǎn)換是否成功if d 0 d fun2 intmain Baseb fun 運行結(jié)果 Base fun1 Derived1 fun1 Derived1 fun2 Derived2 fun1 Derived2 fun2 48 typeid的使用 語法形式typeid 表達(dá)式 typeid 類型說明符 功能獲得表達(dá)式或類型說明符的類型信息表達(dá)式有多態(tài)類型時 會被求值 并得到動態(tài)類型信息 否則 表達(dá)式不被求值 只能得到靜態(tài)的類型信息 類型信息用type info對象表示type info是typeinfo頭文件中聲明的類 typeid的結(jié)果是type info類型的常引用 可以用type info的重載的 操作符比較兩類型的異同 type info的name成員函數(shù)返回類型名稱 類型為constchar 49 深度探索 例8 10typeid示例 include includeusingnamespacestd classBase public virtual Base classDerived publicBase 50 深度探索 voidfun Base b 得到表示b和 b類型信息的對象consttype info 運行結(jié)果 typeid b classBase typeid b classBaseAbaseclass typeid b classBase typeid b classDerived 51 虛函數(shù)動態(tài)綁定的實現(xiàn)原理 動態(tài)選擇被執(zhí)行的函數(shù)函數(shù)的調(diào)用 需要通過函數(shù)代碼的入口地址把函數(shù)入口地址作為變量 在不同情況下賦予不同的值 通過該變量調(diào)用函數(shù) 就可動態(tài)選擇被執(zhí)行的函數(shù)回顧 第6章介紹的函數(shù)指針 指向成員函數(shù)的指針虛表每個多態(tài)類有一個虛表 virtualtable 虛表中有當(dāng)前類的各個虛函數(shù)的入口地址每個對象有一個指向當(dāng)前類的虛表的指針 虛指針vptr 動態(tài)綁定的實現(xiàn)構(gòu)造函數(shù)中為對象的虛指針賦值通過多態(tài)類型的指針或引用調(diào)用成員函數(shù)時 通過虛指針找到虛表 進(jìn)而找到所調(diào)用的虛函數(shù)的入口地址通過該入口地址調(diào)用虛函數(shù) 52 深度探索 53 classBase public virtualvoidf virtualvoidg private inti classDerived publicBase public virtualvoidf 覆蓋Base fvirtualvoidh 新增的虛函數(shù)private intj 深度探索 54 小結(jié)與復(fù)習(xí)建議 主要內(nèi)容多態(tài)性的概念 運算符重載 虛函數(shù) 純虛函數(shù) 抽象類達(dá)到的目標(biāo)理解多態(tài)的概念 學(xué)會運用多態(tài)機(jī)制 實驗任務(wù)實驗八- 1.請仔細(xì)閱讀文檔,確保文檔完整性,對于不預(yù)覽、不比對內(nèi)容而直接下載帶來的問題本站不予受理。
- 2.下載的文檔,不會出現(xiàn)我們的網(wǎng)址水印。
- 3、該文檔所得收入(下載+內(nèi)容+預(yù)覽)歸上傳者、原創(chuàng)作者;如果您是本文檔原作者,請點此認(rèn)領(lǐng)!既往收益都?xì)w您。
下載文檔到電腦,查找使用更方便
14.9 積分
下載 |
- 配套講稿:
如PPT文件的首頁顯示word圖標(biāo),表示該P(yáng)PT已包含配套word講稿。雙擊word圖標(biāo)可打開word文檔。
- 特殊限制:
部分文檔作品中含有的國旗、國徽等圖片,僅作為作品整體效果示例展示,禁止商用。設(shè)計者僅對作品中獨創(chuàng)性部分享有著作權(quán)。
- 關(guān) 鍵 詞:
- 清華大學(xué)出版社 第四 課件 第八
鏈接地址:http://weibangfood.com.cn/p-6330331.html