c++課件第十二章多態(tài)性與虛函數(shù)_第1頁(yè)
c++課件第十二章多態(tài)性與虛函數(shù)_第2頁(yè)
c++課件第十二章多態(tài)性與虛函數(shù)_第3頁(yè)
c++課件第十二章多態(tài)性與虛函數(shù)_第4頁(yè)
c++課件第十二章多態(tài)性與虛函數(shù)_第5頁(yè)
已閱讀5頁(yè),還剩25頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、第12章 多態(tài)性與虛函數(shù)12.1多態(tài)性的概念多態(tài)性分為兩類:靜態(tài)多態(tài)性和動(dòng)態(tài)多態(tài)性。靜態(tài)多態(tài)性是通過(guò)函數(shù)重載和運(yùn)算符號(hào)重載實(shí)現(xiàn)的多態(tài),在程序編譯時(shí)就能決定調(diào)用的是哪一個(gè)函數(shù),靜態(tài)多態(tài)性也稱為編譯時(shí)的多態(tài)性。動(dòng)態(tài)多態(tài)性是在程序運(yùn)行過(guò)程中動(dòng)態(tài)地確定操作所確定的對(duì)象,動(dòng)態(tài)多態(tài)性是通過(guò)虛函數(shù)實(shí)現(xiàn)的。12.2一個(gè)典型的例子例12.1 先建立一個(gè)Point(點(diǎn))類,包含數(shù)據(jù)成員x,y(坐標(biāo)點(diǎn))。以它為基類,派生出一個(gè)Circle(圓)類,增加數(shù)據(jù)成員r(半徑),再以Circle類為直接基類,派生出一個(gè)Cylinder(圓柱體)類,在增加數(shù)據(jù)成員h(高)。要求編寫(xiě)程序,重載運(yùn)算符“”,使之能用于輸出以上類對(duì)

2、象。#include using namespace std;/聲明類Pointclass Pointpublic:Point(float=0,float=0);void setPoint(float,float);float getX() const return x;float getY() const return y; friend ostream & operator(ostream &,const Point &);protected:float x,y;/定義Point類的成員函數(shù)/Point的構(gòu)造函數(shù)Point:Point(float a,float b)x=a;y=b;/設(shè)置

3、x和y的坐標(biāo)值void Point:setPoint(float a,float b)x=a;y=b;/輸出點(diǎn)的坐標(biāo)ostream & operator(ostream &output,const Point &p)outputp.x,p.yendl; return output;int main()Point p(3.5,6.4);coutx=p.getX(),y=p.getY()endl;p.setPoint(8.5,6.8);coutp(new):pendl;return 0;x=3.5,y=6.4p(new):8.5,6.8#include using namespace std;/聲

4、明類Pointclass Pointpublic: Point(float=0,float=0); void setPoint(float,float); float getX() const return x; float getY() const return y; friend ostream & operator(ostream &,const Point &);protected: float x,y;/定義Point類的成員函數(shù)/Point的構(gòu)造函數(shù)Point:Point(float a,float b)x=a;y=b;/設(shè)置x和y的坐標(biāo)值void Point:setPoint(f

5、loat a,float b)x=a;y=b;/輸出點(diǎn)的坐標(biāo)ostream & operator(ostream &output,const Point &p)outputp.x,p.yendl; return output;class Circle:public Pointpublic: Circle(float x=0,float y=0,float r=0); void setRadius(float); float getRadius() const; float area () const; friend ostream &operator(ostream &,const Circl

6、e &); private: float radius;Circle:Circle(float a,float b,float r) :Point(a,b),radius(r)void Circle:setRadius(float r)radius=r;float Circle:getRadius() const return radius;float Circle:area() constreturn 3.14159*radius*radius;ostream &operator(ostream &output,const Circle &c)outputCenter=c.x,c.y, Ra

7、dius=c.radius, area=c.area()endl; return output;int main()Circle c(3.5,6.4,5.2); coutoriginal circle:nx=c.getX(), y=c.getY(), r=c.getRadius() , area=c.area()endl; c.setRadius(7.5); c.setPoint(5,5); coutnew circle:nc; Point &pRef=c; coutpRef:pRef; return 0;original circle:x=3.5, y=6.4, r=5.2, area=84

8、.9486new circle:Center=5,5, Radius=7.5, area=176.714pRef:5,5#include using namespace std;class Pointpublic: Point(float=0,float=0); void setPoint(float,float); float getX() const return x; float getY() const return y; friend ostream & operator(ostream &,const Point &);protected: float x,y;Point:Poin

9、t(float a,float b)x=a;y=b;void Point:setPoint(float a,float b)x=a;y=b;ostream & operator(ostream &output,const Point &p)outputp.x,p.yendl; return output;class Circle:public Pointpublic: Circle(float x=0,float y=0,float r=0); void setRadius(float); float getRadius() const; float area () const; friend

10、 ostream &operator(ostream &,const Circle &); protected: float radius;Circle:Circle(float a,float b,float r) :Point(a,b),radius(r)void Circle:setRadius(float r)radius=r;float Circle:getRadius() const return radius;float Circle:area() constreturn 3.14159*radius*radius;ostream &operator(ostream &outpu

11、t,const Circle &c)outputCenter=c.x,c.y,r= c.radius, area=c.area()endl; return output;class Cylinder:public Circlepublic: Cylinder(float x=0,float y=0,float r=0,float h=0); void setHeight(float); /設(shè)置圓柱高 float getHeight() const;/讀取圓柱高 float area() const; /計(jì)算圓柱表面積 float volume() const;/計(jì)算圓柱體積 friend os

12、tream& operator(ostream&,const Cylinder&); protected: float height;Cylinder:Cylinder(float a,float b,float r,float h) :Circle(a,b,r),height(h)void Cylinder:setHeight(float h)height=h;float Cylinder:getHeight() const return height;float Cylinder:area() const return 2*Circle:area()+2*3.14159*radius*he

13、ight;float Cylinder:volume() constreturn Circle:area()*height;ostream &operator(ostream &output,const Cylinder& cy)outputCenter=cy.x,cy.y, r=cy.radius, h=cy.height narea=cy.area(), volume=cy.volume()endl; return output;int main()Cylinder cy1(3.5,6.4,5.2,10); coutnoriginal cylinder:nx=cy1.getX(), y=

14、cy1.getY(), r=cy1.getRadius(), h= cy1.getHeight()narea=cy1.area() , volume=cy1.volume()endl; cy1.setHeight(15); cy1.setRadius(7.5); cy1.setPoint(5,5); coutnnew cylinder:ncy1; Point &pRef=cy1; coutnpRef as a point:pRef; Circle &cRef=cy1; coutncRef as a Circle:cRef; return 0;original cylinder:x=3.5, y

15、=6.4, r=5.2, h=10area=496.623, volume=849.486new cylinder:Center=5,5, r=7.5, h=15area=1060.29, volume=2650.72pRef as a point:5,5cRef as a Circle:Center=5,5, r=7.5, area=176.71412.3虛函數(shù)12.3.1虛函數(shù)的作用例12.2 基類與派生類有同名函數(shù)#include #include using namespace std;class Studentpublic: Student(int,string,float); /v

16、irtual void display();void display();protected: int num; string name; float score;Student:Student(int n,string nam,float s)num=n;name=nam;score=s;void Student:display()coutnum:numnname:namenscore:scorenn;class Graduate:public Studentpublic: Graduate(int,string,float,float); void display();private: f

17、loat pay;void Graduate:display()coutnum:numnname:namenscore:scorenpay=paydisplay();pt=&grad1;pt-display();return 0;num:1001name:Liscore:87.5num:2001name:Wangscore:98.5如果void display();改為 virtual void display();則輸出多一行:pay=563.5這種使用virtual修飾的成員函數(shù)稱為虛函數(shù)。當(dāng)在派生類中定義了一個(gè)同名的成員函數(shù)時(shí),只要該成員函數(shù)的參數(shù)個(gè)數(shù)和相應(yīng)類型以及它的返回類型與基類中同

18、名的虛函數(shù)完全一樣,則無(wú)論是否為該成員函數(shù)使用virtual,它都將成為一個(gè)虛函數(shù)。使用虛函數(shù)保證了在通過(guò)一個(gè)基類類型的指針(包括引用)調(diào)用一個(gè)虛函數(shù)時(shí),系統(tǒng)對(duì)該調(diào)用進(jìn)行動(dòng)態(tài)關(guān)聯(lián),即此時(shí)調(diào)用的是指針變量指向的對(duì)象的同名函數(shù)。但是,在通過(guò)一對(duì)象訪問(wèn)一虛函數(shù)時(shí),則使用靜態(tài)關(guān)聯(lián)。12.3.2靜態(tài)關(guān)聯(lián)與動(dòng)態(tài)關(guān)聯(lián) 12.3.3在什么情況下應(yīng)當(dāng)聲明虛函數(shù)12.3.4虛析構(gòu)函數(shù)例12.3 基類中有非虛析構(gòu)函數(shù)時(shí)的執(zhí)行情況。#include using namespace std;class Pointpublic: Point()virtual Point()coutexecuting Point dest

19、ructorendl;class Circle:public Pointpublic:Circle()Circle() coutexecuting Circle destructorendl;private:int radus;int main()Point *p=new Circle;delete p;return 0;executing Point destructor如果將Point()coutexecuting Point destructorendl;改寫(xiě)為virtual Point()coutexecuting Point destructorendl;則輸出結(jié)構(gòu)為:executi

20、ng Circle destructorexecuting Point destructor顯然這是我們想要的結(jié)果,因此,為了使用動(dòng)態(tài)內(nèi)存(new delete),應(yīng)將基類的析構(gòu)函數(shù)聲明為虛析構(gòu)函數(shù)。12.4純虛函數(shù)與抽象類12.4.1純虛函數(shù)virtual float area() const return 0;/空虛函數(shù)virtual float area() const =0;/純虛函數(shù)純虛函數(shù)沒(méi)有函數(shù)體,也沒(méi)有給它分配內(nèi)存。它的定義留給派生類來(lái)做。12.4.2抽象類一個(gè)類可以說(shuō)明多個(gè)純虛函數(shù),包含有純虛函數(shù)的類稱為抽象類。一個(gè)抽象類只能作為基類來(lái)派生新類,不能說(shuō)明抽象類的對(duì)象。說(shuō)明了純

21、虛函數(shù)的派生類仍是抽象類。如果派生類中給出了基類所有純虛函數(shù)的實(shí)現(xiàn),則該派生類不再是抽象類。/使用純虛函數(shù)的例子。#includeclass numberprotected: int val;public: number(int i)val = i; virtual void show() = 0;class hextype : public numberpublic: hextype(int i) : number(i) void show()couthexvaldecendl;class dectype : public numberpublic:dectype(int i) : numb

22、er(i)void show()coutdecvalshow();hextype h(15);nump=&h;nump-show();56f12.4.3應(yīng)用實(shí)例例12.4 虛函數(shù)和抽象基類的應(yīng)用。#include using namespace std;/聲明抽象基類Shapeclass Shapepublic: virtual float area() const return 0.0;/虛函數(shù) virtual float volume() const return 0.0;/虛函數(shù) virtual void shapeName() const =0;/純虛函數(shù);/聲明Point類 Poin

23、t是Shape的公用派生類class Point:public Shape public: Point(float=0,float=0); void setPoint(float,float); float getX() const return x; float getY() const return y; virtual void shapeName() const coutPoint:; /對(duì)純虛函數(shù)進(jìn)行定義 friend ostream & operator(ostream &,const Point &);protected: float x,y;Point:Point(float

24、a,float b)x=a;y=b;void Point:setPoint(float a,float b)x=a;y=b;ostream & operator(ostream &output,const Point &p)outputp.x,p.y; return output;/聲明Circle類class Circle:public Pointpublic: Circle(float x=0,float y=0,float r=0); void setRadius(float); float getRadius() const; virtual float area() const; v

25、irtual void shapeName() const coutCircle:; /對(duì)純虛函數(shù)進(jìn)行再定義 friend ostream &operator(ostream &,const Circle &); protected: float radius;Circle:Circle(float a,float b,float r) :Point(a,b),radius(r)void Circle:setRadius(float r)radius=r;float Circle:getRadius() const return radius;float Circle:area() const

26、return 3.14159*radius*radius;ostream &operator(ostream &output,const Circle &c)outputc.x,c.y, r=c.radius; return output;/聲明Cylinder類class Cylinder:public Circlepublic: Cylinder (float x=0,float y=0,float r=0,float h=0); void setHeight(float); float getHeight() const; virtual float area() const; virt

27、ual float volume() const; virtual void shapeName() const coutCylinder:; /對(duì)純虛函數(shù)進(jìn)行再定義 friend ostream& operator(ostream&,const Cylinder&); protected: float height;Cylinder:Cylinder(float a,float b,float r,float h) :Circle(a,b,r),height(h)void Cylinder:setHeight(float h)height=h;float Cylinder:getHeight

28、() const return height;float Cylinder:area() const return 2*Circle:area()+2*3.14159*radius*height;float Cylinder:volume() constreturn Circle:area()*height;ostream &operator(ostream &output,const Cylinder& cy)outputcy.x,cy.y, r=cy.radius , h=cy.height; return output;int main()Point point(3.2,4.5); /建

29、立Point類對(duì)象point Circle circle(2.4,12,5.6);/建立Circle類對(duì)象circle Cylinder cylinder(3.5,6.4,5.2,10.5);/建立Cylinder類對(duì)象cylinder point.shapeName();/靜態(tài)關(guān)聯(lián) coutpointendl; circle.shapeName();/靜態(tài)關(guān)聯(lián) coutcircleendl; cylinder.shapeName();/靜態(tài)關(guān)聯(lián) coutcylinderendlshapeName(); /動(dòng)態(tài)關(guān)聯(lián) coutx=point.getX(),y=point.getY()narea=

30、 area()nvolume=volume()shapeName(); /動(dòng)態(tài)關(guān)聯(lián) coutx=circle.getX(),y=circle.getY()narea= area()nvolume=volume()shapeName();/動(dòng)態(tài)關(guān)聯(lián) coutx=cylinder.getX(),y=cylinder.getY() narea=area()nvolume=volume()nn; return 0;Point:3.2,4.5Circle:2.4,12, r=5.6Cylinder:3.5,6.4, r=5.2, h=10.5Point:x=3.2,y=4.5area=0volume=0

31、Circle:x=2.4,y=12area=98.5203volume=0Cylinder:x=3.5,y=6.4area=512.959volume=891.96例編寫(xiě)一個(gè)用于計(jì)算各類形狀的總面積的例子。這個(gè)程序用于計(jì)算各類形狀的總面積。由于尚不能確定該程序處理的具體形狀,我們先定義一個(gè)抽象的shape類。/shape.hclass shape public: virtual float area()=0;float total(shape *s,int n);有了shape類,就可以開(kāi)始設(shè)計(jì)求面積程序:/shape.cpp#include shape.h#include float tot

32、al(shape * s ,int n)float sum = 0;for(int i=0;iarea();coutarea()endl;return sum;該程序可以用于求各類形狀的面積之和。對(duì)于具體種類的形狀,通過(guò)從shape派生一個(gè)類來(lái)對(duì)其進(jìn)行描述,以重用上面的代碼,并且不用重新對(duì)這些碼進(jìn)行編譯。也就是說(shuō),可以把函數(shù)total()放在一個(gè)程序庫(kù)中,以便其它程序在需要使用。例如:#include#includeshape.hclass triangle : public shapeprotected : float H , W;public:triangle(float h , floa

33、t w) H = h ; W = w ;float area() return H * W * 0.5 ; ;class rectangle :public triangle public :rectangle(float h, float w) :triangle(h,w) float area() return H * W ;class circle : public shape protected : float radius ;public : circle(float r ) radius = r; float area()return radius * radius * 3.14;

34、 ;void main()shape *s4 ;s0 = new triangle(3.0,4.0);s1 = new rectangle(2.0,4.0) ;s2 = new circle(5.0) ;s3 = new circle(8.0) ;float sum = total(s,4) ;cout sumendl;delete s0;delete s1;delete s2;delete s3;在該例中,shape類中的虛函數(shù)area僅起到為派生類提供一個(gè)一致的接口的作用,派生類中重定義的area() 用于決定以什么的方式計(jì)算面積。由于在shape類中不能對(duì)此作用決定,因此被說(shuō)明為純虛函數(shù)

35、。從此例子可以看出,賦值兼容規(guī)則使我們可將正方形、三角形、圓都視為形狀,多態(tài)性又保證了函數(shù)total在對(duì)各種形狀求面積之和時(shí),無(wú)須關(guān)心當(dāng)前正在計(jì)算哪種具體形狀的面積。在需要時(shí),函數(shù)total可從這些形狀的對(duì)象那里獲得該對(duì)象的面積,成員函數(shù)area保證了這點(diǎn)。特別聲明:最好使用虛析構(gòu)函數(shù)。#include class shape public: virtual float area()=0; virtual shape()coutdel shapen;float total(shape * s ,int n)float sum = 0;for(int i=0;iarea();coutarea()

36、endl;return sum;class triangle : public shapeprotected : float H , W;public:triangle(float h , float w) H = h ; W = w ;float area() return H * W * 0.5 ; triangle()coutdel trianglen;class rectangle :public triangle public :rectangle(float h, float w) :triangle(h,w) rectangle()coutdel rectanglen;float

37、 area() return H * W ;class circle : public shape protected : float radius ;public : circle(float r ) radius = r;circle()coutdel circlen; float area()return radius * radius * 3.14; ;void main()shape *s4 ;s0 = new triangle(3.0,4.0);s1 = new rectangle(2.0,4.0) ;s2 = new circle(5.0) ;s3 = new circle(8.

38、0) ;float sum = total(s,4) ;cout sumendl;delete s0;delete s1;delete s2;delete s3;6878.5200.96293.46del triangledel shapedel rectangledel triangledel shapedel circledel shapedel circledel shape實(shí)驗(yàn):1:實(shí)驗(yàn)?zāi)康模?1)了解多態(tài)性的概念。(2)了解虛函數(shù)的作用及使用方法。(3)了解靜態(tài)關(guān)聯(lián)和動(dòng)態(tài)關(guān)聯(lián)的概念和用法。(4)了解純虛函數(shù)和抽象類的概念和用法。2:實(shí)驗(yàn)內(nèi)容: P416 1 43:實(shí)驗(yàn)結(jié)果。下面是虛析

39、構(gòu)函數(shù)的真正用途例子,供有興趣同學(xué)參考。數(shù)據(jù)庫(kù)中保存各類對(duì)象的例子。/database.hclass object public:virtual int isEqual(object&)=0;virtual object();class database private:object* rec100;int pc,iterPc; public:database()pc=iterPc=0;int add(object&);object* read();void rewind()iterPc=0;int GetPc()return pc;int GetIterpc()return iterPc;d

40、atabase();database類的成員函數(shù)add()用于向數(shù)據(jù)庫(kù)中增添一個(gè)對(duì)象,read() 對(duì)數(shù)據(jù)庫(kù)進(jìn)行順序讀,并返回讀到的每一個(gè)對(duì)象,當(dāng)所有對(duì)象被讀完時(shí),返回0。為使同一個(gè)對(duì)象在數(shù)據(jù)庫(kù)中不保存兩個(gè)備份,add()要將欲加入的對(duì)象與數(shù)據(jù)庫(kù)中的對(duì)象進(jìn)行相等比較,object類中的成員函數(shù)isEqual()用于比較對(duì)象,當(dāng)兩個(gè)對(duì)象相等時(shí),它返回1。因?yàn)樵跊](méi)有明確具體種類的對(duì)象之前,無(wú)法給出isEqual()的定義,所以,它被說(shuō)明為純虛函數(shù)。/database.cpp#includedatabase.hint database : add(object& obj) for (int i=0;

41、iisEqual(obj)return 0;recpc+=&obj;return 1;object * database : read() if(iterPc pc) return reciterPc+; else return 0;database : database()for(int i=0;ipc;i+)delete reci;下面是使用這個(gè)程序的示例程序。/univ.h#include#include#include”database.h”class person : public objectprotected: char * name; person()name=0;public

42、:person(char *s)name=new charstrlen(s)+1;strcpy(name,s);virtual void print()=0;int isEqual(object& obj)person& man=(person&)obj;return strcmp(name, )=0;person()delete name;class student : virtual public person private: int val; public: student(char * s,int l):person(s)val=l; void print()cout

43、name valprint();univ.rewind();while(p=univ.read()!=0)p-print(); 讀者分析一下該程序中虛析構(gòu)函數(shù)的作用。如果不使用虛析構(gòu)函數(shù),在程序結(jié)束時(shí),person類的成員name所指向的一段內(nèi)存就不能釋放。另外應(yīng)注意,從databade類派生univDBase類目的是為替換database類的接口:使read返回一個(gè)person類類型的指針,這樣,main函數(shù)就比較清晰可讀。由于目前數(shù)據(jù)庫(kù)中只保存person類的對(duì)象,所以,在函數(shù)read中進(jìn)行強(qiáng)制類型轉(zhuǎn)換是安全的。從這個(gè)程序可以看出,基類定義了比派生類更大的對(duì)象集合,因此,基于基類所做的抽象

44、所設(shè)計(jì)的程序必然可以用于派生類這種具體情形。將多個(gè)類中的共性抽象到基類中以便重用代碼,這是面向?qū)ο蠛统绦蛟O(shè)計(jì)方法的一個(gè)重要思想,多態(tài)性從語(yǔ)言的實(shí)現(xiàn)上為代碼重用提供了有力的支持。測(cè)試實(shí)例:#include#include/#includedatabase.hclass object public:virtual int isEqual(object&)=0;virtual object()coutobjectendl;class database private:object* rec100;int pc,iterPc; public:database()pc=iterPc=0;int add(

45、object&);object* read();void rewind()iterPc=0;int GetPc()return pc;int GetIterpc()return iterPc;database();int database : add(object& obj) for (int i=0;iisEqual(obj)return 0;recpc+=&obj;return 1;object * database : read()/coutdatabase read pc iterPcendl;if(iterPc pc)coutfff database read pc iterPcendl;return reciterPc+;else coutend database read pc iterPcendl; return 0;database : database()for(int i=0;ipc;i+)delete reci;class person : public objectprotected: char *

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論