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