C++程序設(shè)計(jì)基礎(chǔ)第12章-虛函數(shù)與多態(tài)性課件_第1頁
C++程序設(shè)計(jì)基礎(chǔ)第12章-虛函數(shù)與多態(tài)性課件_第2頁
C++程序設(shè)計(jì)基礎(chǔ)第12章-虛函數(shù)與多態(tài)性課件_第3頁
C++程序設(shè)計(jì)基礎(chǔ)第12章-虛函數(shù)與多態(tài)性課件_第4頁
C++程序設(shè)計(jì)基礎(chǔ)第12章-虛函數(shù)與多態(tài)性課件_第5頁
已閱讀5頁,還剩25頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

第12章虛函數(shù)與多態(tài)性主講:李政偉第12章虛函數(shù)與多態(tài)性主講:李政偉2第12章虛函數(shù)與多態(tài)性12.1多態(tài)性的概念12.2虛函數(shù)的定義12.3抽象類12.4實(shí)例研究2第12章虛函數(shù)與多態(tài)性12.1多態(tài)性的概念3多態(tài)性是OOP的重要特征之一。多態(tài)一詞最初來源于希臘語Polumorphos,含義是具有多種形式或形態(tài)的情形。多態(tài)性:發(fā)出同樣的消息被不同類型的對象接收時(shí)會導(dǎo)致完全不同的行為。多態(tài)性:父類型具有“引用由它派生的任何子類型”的能力。多態(tài)的實(shí)現(xiàn)途徑函數(shù)重載運(yùn)算符重載虛函數(shù)12.1多態(tài)性(polymorphism)的概念靜態(tài)多態(tài)動(dòng)態(tài)多態(tài)3多態(tài)性是OOP的重要特征之一。12.1多態(tài)性(polym4函數(shù)重載:在同一作用域內(nèi)的多個(gè)函數(shù)采用相同名字,只要使用不同類型、不同數(shù)目的參數(shù)。作為重載函數(shù):(1)至少在參數(shù)個(gè)數(shù)、參數(shù)類型上有所不同。(2)使用缺省函數(shù)參數(shù)要注意二義性。如:voidprint(inta,intb);voidprint(inta,intb,intc=50);

print(10,100);12.1多態(tài)性(polymorphism)的概念4函數(shù)重載:在同一作用域內(nèi)的多個(gè)函數(shù)采用相同名字,只要使用不512.1多態(tài)性(polymorphism)的概念運(yùn)算符重載:對已有的運(yùn)算符賦予多重含義。必要性C++中預(yù)定義運(yùn)算符其運(yùn)算對象只能是標(biāo)準(zhǔn)數(shù)據(jù)類型,而不適用于用戶自定義類型(如類)。實(shí)現(xiàn)機(jī)制將指定的運(yùn)算表達(dá)式轉(zhuǎn)化為對運(yùn)算符函數(shù)的調(diào)用,運(yùn)算對象轉(zhuǎn)化為運(yùn)算符函數(shù)的實(shí)參。512.1多態(tài)性(polymorphism)的概念運(yùn)算符重6分類——系統(tǒng)實(shí)現(xiàn)的角度靜態(tài)多態(tài)性:在編譯時(shí)系統(tǒng)就能決定調(diào)用哪個(gè)函數(shù),又稱編譯時(shí)的多態(tài)性。函數(shù)重載、運(yùn)算符重載動(dòng)態(tài)多態(tài)性:在運(yùn)行過程中才動(dòng)態(tài)確定操作所針對的對象。又稱運(yùn)行時(shí)多態(tài)。虛函數(shù)(virtualfunction)12.1多態(tài)性(polymorphism)的概念6分類——系統(tǒng)實(shí)現(xiàn)的角度12.1多態(tài)性(polymorph7classPoint{public:

Point(doublei,doublej){x=i;y=j;} doubleArea()const{return0.0;}private:doublex,y;};classRectangle:publicPoint{public: Rectangle(doublei,doublej,doublek,doublel); doubleArea()const{returnw*h;}private: doublew,h;};例12.1非虛函數(shù)舉例7classPoint例12.1非虛函數(shù)舉例8Rectangle::Rectangle(doublei,doublej,doublek,doublel):Point(i,j){ w=k;h=l;}voidfun(Point&Pref){ cout<<"Area="<<Pref.Area()<<endl;}voidmain(){ Rectanglerec(3.0,6.0,15.0,20.0); fun(rec);}例12.1非虛函數(shù)舉例8Rectangle::Rectangle(doublei注意事項(xiàng)派生類對象指針使用時(shí)應(yīng)注意的問題:(1)聲明為指向基類對象的指針可以指向它的公有派生類的對象,但不允許指向它的私有派生類的對象。(2)允許聲明為指向基類對象的指針指向它的公有派生類的對象,但不允許將一個(gè)聲明為指向派生類對象的指針指向基類的對象。(3)聲明為指向基類對象的指針,當(dāng)其指向它的公有派生類的對象時(shí),只能直接訪問派生類中從基類繼承下來的成員,不能直接訪問公有派生類中定義的成員。要想訪問其公有派生類中的成員,可將基類指針用顯式類型轉(zhuǎn)換方式轉(zhuǎn)換為派生類指針。注意事項(xiàng)派生類對象指針使用時(shí)應(yīng)注意的問題:1012.3虛函數(shù)12.3.1虛函數(shù)的作用同一類中不能定義名字,參數(shù)個(gè)數(shù)和類型都相同的函數(shù),不能“重復(fù)定義”。不同層次中可以出現(xiàn)名字、參數(shù)個(gè)數(shù)和類型都相同而功能不同的函數(shù)。系統(tǒng)按照同名覆蓋的原則決定調(diào)用對象。rc1.area()

//派生類Rectangle的成員函數(shù)。rc1.Point::area()

//基類Point的成員函數(shù)Pref.area()1012.3虛函數(shù)12.3.1虛函數(shù)的作用11虛函數(shù)的聲明形式virtual<函數(shù)類型><函數(shù)名>(<參數(shù)列表>){函數(shù)體}成員函數(shù),非static成員函數(shù)有繼承性,基類中定義了虛函數(shù),派生類中無論是否說明,同原型函數(shù)都自動(dòng)為虛函數(shù)。作用:通過基類指針或引用調(diào)用執(zhí)行時(shí)根據(jù)指針指向的對象類型動(dòng)態(tài)決定調(diào)用哪個(gè)函數(shù)。12.3虛函數(shù)11虛函數(shù)的聲明形式12.3虛函數(shù)12classA{public:

virtualvoiddisplay(){cout<<“A::display()";}};classB:publicA{public: voiddisplay()//自動(dòng)成為虛函數(shù){cout<<“B::display()";}};classC:publicB{public: voiddisplay()//自動(dòng)成為虛函數(shù){cout<<“C::display()"<<endl;}};voidfun(A

*ptr){ptr->display();}voidmain() { Aa1,*p;

Bb1;

Cc1;

p=&a1; fun(p);

p=&b1; fun(p);

p=&c1; fun(p);}12classA{classB:publicAvoi13虛函數(shù)的使用方法

(1)基類中用virtual聲明其為虛函數(shù)(2)要求函數(shù)名、返回類型、參數(shù)個(gè)數(shù)和類型全部與基類的虛函數(shù)相同,根據(jù)需要重新定義函數(shù)體。(3)定義一個(gè)指向基類對象的指針變量,使它指向同一類族中要調(diào)用該函數(shù)的對象。(4)通過該指針變量調(diào)用此虛函數(shù),調(diào)用的是指針變量指向的對象所屬類的同名函數(shù)。例12.2基類與派生類中有同名函數(shù)13虛函數(shù)的使用方法例12.2基類與派生類中有同名函數(shù)14函數(shù)重載可用于普通函數(shù)和類的成員函數(shù);虛函數(shù)只能用于類的成員函數(shù)。函數(shù)重載可用于構(gòu)造函數(shù);虛函數(shù)不可以。重載成員函數(shù)必須屬于同一個(gè)類,為橫向;虛函數(shù)是同一類族中基類和派生類的同原型函數(shù),為縱向。函數(shù)重載要求函數(shù)名字相同,但參數(shù)個(gè)數(shù)或類型不同;虛函數(shù)要求同一類族所有虛函數(shù)的名字、參數(shù)類型、個(gè)數(shù)完全相同。函數(shù)重載在編譯時(shí)確定;虛函數(shù)在程序運(yùn)行時(shí)確定。函數(shù)重載PK虛函數(shù)14函數(shù)重載可用于普通函數(shù)和類的成員函數(shù);虛函數(shù)只能用于類的12.2.3虛函數(shù)的限制使用虛函數(shù)時(shí)應(yīng)注意如下問題:(1)虛函數(shù)聲明只能出現(xiàn)在類聲明的函數(shù)原型的聲明中,不能出現(xiàn)在函數(shù)體實(shí)現(xiàn)中,同時(shí)基類中只有保護(hù)成員或公有成員才能被聲明為虛函數(shù)。(2)派生類中重新定義虛函數(shù)時(shí),關(guān)鍵字virtual可以寫也可不寫,為避免引起混亂,應(yīng)寫上該關(guān)鍵字。(3)動(dòng)態(tài)聯(lián)編只能通過成員函數(shù)來調(diào)用或通過指針、引用來訪問虛函數(shù),如果用對象名的形式來訪問虛函數(shù),將采用靜態(tài)聯(lián)編。(4)構(gòu)造函數(shù)不能聲明為虛函數(shù),析構(gòu)函數(shù)可以聲明為虛函數(shù)12.2.3虛函數(shù)的限制使用虛函數(shù)時(shí)應(yīng)注意如下問題:例12.3基類中有非虛析構(gòu)函數(shù)時(shí)的情況classPoint

//基類Point類{public:Point(){}~Point(){cout<<"executingPointdestructor"<<endl;}};classCircle:publicPoint

//派生類Circle類{public:Circle(){}~Circle(){cout<<"executingCircledestructor"<<endl;}

private:intradius;};intmain(){Point*p=new

Circle;deletep;}executingPointdestructor例12.3基類中有非虛析構(gòu)函數(shù)時(shí)的情況classPoin1712.3.4虛析構(gòu)函數(shù)用new運(yùn)算符建立對象,且定義了指向基類的指針變量。用帶指針參數(shù)的delete運(yùn)算符撤銷對象時(shí):只執(zhí)行基類析構(gòu)函數(shù),而不執(zhí)行派生類的析構(gòu)函數(shù)。1712.3.4虛析構(gòu)函數(shù)用new運(yùn)算符建立對象,且定義了18virtual~Point(){cout<<"executingPointdestructor"<<endl;}executingCircledestructorexecutingPointdestructor例12.3基類中有非虛析構(gòu)函數(shù)時(shí)的情況基類的析構(gòu)函數(shù)為虛函數(shù)時(shí),該基類的所有派生類的析構(gòu)函數(shù)都自動(dòng)成為虛函數(shù),即使兩者的名字不同。推薦:基類析構(gòu)函數(shù)聲明為虛函數(shù)。18virtual~Point(){cout<<"exec1912.4純虛函數(shù)與抽象類12.4.1純虛函數(shù)基類中成員函數(shù)設(shè)為虛函數(shù),一般并不是基類本身的要求,而是考慮到派生類的需要?;怭oint沒有求面積的Area函數(shù),“點(diǎn)”沒有面積,基類本身不需要這個(gè)函數(shù)。直接派生類Circle和間接派生類Rectangle中都需要Area函數(shù),且功能不同。1912.4純虛函數(shù)與抽象類12.4.1純虛函數(shù)2012.4.1純虛函數(shù)virtualfloatarea()const{return0;}

//虛函數(shù)virtualfloatarea()const=0;//純虛函數(shù)純虛函數(shù)(purevirtualfunction):在聲明虛函數(shù)時(shí)被“初始化”為0的函數(shù)。純虛函數(shù)的聲明格式:virtual

函數(shù)類型函數(shù)名(參數(shù)表列)=0;注:①無函數(shù)體;②“=0”不表示返回值為0,只用來告知是純虛函數(shù);③以分號結(jié)束。2012.4.1純虛函數(shù)virtualfloatare21只有函數(shù)名字而不具備函數(shù)的功能,不能被調(diào)用。只是通知編譯系統(tǒng):"這里聲明一個(gè)虛函數(shù),留待派生類中定義"。作用:基類中為其保留了函數(shù)名字,以便派生類根據(jù)需要對它進(jìn)行定義。若基類聲明了純虛函數(shù),而派生類沒有定義,則該虛函數(shù)在派生類中仍然為純虛函數(shù)。12.4.1純虛函數(shù)21只有函數(shù)名字而不具備函數(shù)的功能,不能被調(diào)用。只是通知編譯2212.4.2抽象類(abstractclass)定義1:不能用來定義對象而只作為基類的類。定義2:帶有純虛函數(shù)的類。一種特殊的類,它為一族類提供統(tǒng)一的操作界面,處于繼承層次結(jié)構(gòu)的較上層。作用:通過它多態(tài)地使用其中的成員函數(shù)。描述了一組子類共同的操作接口,而完整的實(shí)現(xiàn)留給了子類。只能作為基類,不能實(shí)例化。但可以聲明抽象類的指針和引用,指向并訪問派生類的對象。若在派生類中對抽象類的所有純虛函數(shù)進(jìn)行了定義,派生類就成了具體類。若在派生類中沒有對所有純虛函數(shù)進(jìn)行定義,則此派生類仍為抽象類。2212.4.2抽象類(abstractclass)定義23例12.4虛函數(shù)和抽象基類的應(yīng)用例12.4虛函數(shù)和抽象基類的應(yīng)用。對Point為基類的點(diǎn)—圓—圓柱體類的層次結(jié)構(gòu)進(jìn)行改寫,要求使用虛函數(shù)和抽象基類。頂層是抽象基類Shape(形狀)。Point(點(diǎn)),Circle(圓),Cylinder(圓柱體)都是Shape類的直接派生類和間接派生類。23例12.4虛函數(shù)和抽象基類的應(yīng)用例12.4虛函數(shù)和抽24第(1)部分classShape

//抽象基類Shape{public:

virtualfloatarea()const{return0.0;}

virtualfloatvolume()const{return0.0;}

virtualvoidshapeName()const=0;};24第(1)部分classShape//抽象基類Shap25第(2)部分classPoint:publicShape

//Shape的公用派生類{public:Point(float=0,float=0);voidsetPoint(float,float);floatgetX()const{returnx;}floatgetY()const{returny;}

virtualvoidshapeName()const{cout<<"Point:";}

friendostream&operator<<(ostream&,constPoint&);protected:floatx,y;};25第(2)部分classPoint:publicSh26classCircle:publicPoint

//Circle類{public:Circle(floatx=0,floaty=0,floatr=0);voidsetRadius(float);floatgetRadius()const;virtualfloatarea()const;

virtualvoidshapeName()const{cout<<"Circle:";}

friendostream&operator<<(ostream&,constCircle&);protected:

floatradius;};第(3)部分26classCircle:publicPoint/27Circle::Circle(floata,floatb,floatr):Point(a,b),radius(r){}voidCircle::setRadius(floatr):radius(r){}floatCircle::getRadius()const{returnradius;}floatCircle::area()const{return3.14159*radius*radius;}ostream&operator<<(ostream&output,constCircle&c){output<<"["<<c.x<<","<<c.y<<"],r="<<c.radius;returnoutput;}第(3)部分27Circle::Circle(floata,float28第(4)部分classCylinder:publicCircle

//Cylinder類{public:Cylinder(floatx=0,floaty=0,floatr=0,floath=0);voidsetHeight(float);virtualfloatarea()const;virtualfloatvolume()const;

virtualvoidshapeName()const{cout<<"Cylinder:";}

friendostream&operator<<(ostream&,constCylinder&);protected:floatheight;};28第(4)部分classCylinder:public29Cylinder::Cylinder(floata,floatb,floatr,floath):Circle(a,b,r),height(h){}floatCylinder::area()const{return2*Circle::area()+2*3.14159*radius*height;}floatCylinder::volume()const{returnCircle::area()*height;}ostream&operator<<(ostream&output,constCylinder&cy){output<<"["<<cy.x<<","<<cy.y<<"],r="<<cy.radius<<",h="<<cy.height;returnoutput;}第(4)部分29Cylinder::Cylinder(floata,f30intmain(){Pointpoint(3.2,4.5);Circlecircle(2.4,1.2,5.6);Cylindercylinder(3.5,6.4,5

溫馨提示

  • 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

提交評論