c++課件第十二章多態性與虛函數_第1頁
c++課件第十二章多態性與虛函數_第2頁
c++課件第十二章多態性與虛函數_第3頁
c++課件第十二章多態性與虛函數_第4頁
c++課件第十二章多態性與虛函數_第5頁
已閱讀5頁,還剩26頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、.第12章 多態性與虛函數12.1多態性的概念多態性分為兩類:靜態多態性和動態多態性。靜態多態性是通過函數重載和運算符號重載實現的多態,在程序編譯時就能決定調用的是哪一個函數,靜態多態性也稱為編譯時的多態性。動態多態性是在程序運行過程中動態地確定操作所確定的對象,動態多態性是通過虛函數實現的。12.2一個典型的例子例12.1 先建立一個Point點類,包含數據成員x,y坐標點。以它為基類,派生出一個Circle圓類,增加數據成員r半徑,再以Circle類為直接基類,派生出一個Cylinder圓柱體類,在增加數據成員h高。要求編寫程序,重載運算符“<<和“>>,使之能用于

2、輸出以上類對象。#include <iostream>using namespace std;/聲明類Pointclass Pointpublic:Pointfloat=0,float=0;void setPointfloat,float;float getX const return x;float getY const return y; friend ostream & operator<<ostream &,const Point &protected:float x,y;/定義Point類的成員函數/Point的構造函數Point:Po

3、intfloat a,float bx=a;y=b;/設置x和y的坐標值void Point:setPointfloat a,float bx=a;y=b;/輸出點的坐標ostream & operator<<ostream &output,const Point &poutput<<""<<p.x<<","<<p.y<<""<<endl; return output;int mainPoint p3.5,6.4;cout<

4、;<"x="<<p.getX<<",y="<<p.getY<<endl;p.setPoint8.5,6.8;cout<<"pnew:"<<p<<endl;return 0;x=3.5,y=6.4pnew:8.5,6.8#include <iostream>using namespace std;/聲明類Pointclass Pointpublic: Pointfloat=0,float=0; void setPointfloat,fl

5、oat; float getX const return x; float getY const return y; friend ostream & operator<<ostream &,const Point &protected: float x,y;/定義Point類的成員函數/Point的構造函數Point:Pointfloat a,float bx=a;y=b;/設置x和y的坐標值void Point:setPointfloat a,float bx=a;y=b;/輸出點的坐標ostream & operator<<ostr

6、eam &output,const Point &poutput<<""<<p.x<<","<<p.y<<""<<endl; return output;class Circle:public Pointpublic: Circlefloat x=0,float y=0,float r=0; void setRadiusfloat; float getRadius const; float area const; friend ostream &a

7、mp;operator<<ostream &,const Circle & private: float radius;Circle:Circlefloat a,float b,float r :Pointa,b,radiusrvoid Circle:setRadiusfloat rradius=r;float Circle:getRadius const return radius;float Circle:area constreturn 3.14159*radius*radius;ostream &operator<<ostream &am

8、p;output,const Circle &coutput<<"Center="<<c.x<<","<<c.y<<", Radius="<<c.radius<<", area="<<c.area<<endl; return output;int mainCircle c3.5,6.4,5.2; cout<<"original circle:nx="<<c.

9、getX<<", y="<<c.getY<<", r="<<c.getRadius <<", area="<<c.area<<endl; c.setRadius7.5; c.setPoint5,5; cout<<"new circle:n"<<c; Point &pRef=c; cout<<"pRef:"<<pRef; return 0;original c

10、ircle:x=3.5, y=6.4, r=5.2, area=84.9486new circle:Center=5,5, Radius=7.5, area=176.714pRef:5,5#include <iostream>using namespace std;class Pointpublic: Pointfloat=0,float=0; void setPointfloat,float; float getX const return x; float getY const return y; friend ostream & operator<<ost

11、ream &,const Point &protected: float x,y;Point:Pointfloat a,float bx=a;y=b;void Point:setPointfloat a,float bx=a;y=b;ostream & operator<<ostream &output,const Point &poutput<<""<<p.x<<","<<p.y<<""<<endl; retu

12、rn output;class Circle:public Pointpublic: Circlefloat x=0,float y=0,float r=0; void setRadiusfloat; float getRadius const; float area const; friend ostream &operator<<ostream &,const Circle & protected: float radius;Circle:Circlefloat a,float b,float r :Pointa,b,radiusrvoid Circle

13、:setRadiusfloat rradius=r;float Circle:getRadius const return radius;float Circle:area constreturn 3.14159*radius*radius;ostream &operator<<ostream &output,const Circle &coutput<<"Center="<<c.x<<","<<c.y<<",r=" <<c.r

14、adius<<", area="<<c.area<<endl; return output;class Cylinder:public Circlepublic: Cylinderfloat x=0,float y=0,float r=0,float h=0; void setHeightfloat; /設置圓柱高 float getHeight const;/讀取圓柱高 float area const; /計算圓柱外表積 float volume const;/計算圓柱體積 friend ostream& operator&l

15、t;<ostream&,const Cylinder& protected: float height;Cylinder:Cylinderfloat a,float b,float r,float h :Circlea,b,r,heighthvoid Cylinder:setHeightfloat hheight=h;float Cylinder:getHeight const return height;float Cylinder:area const return 2*Circle:area+2*3.14159*radius*height;float Cylinde

16、r:volume constreturn Circle:area*height;ostream &operator<<ostream &output,const Cylinder& cyoutput<<"Center="<<cy.x<<","<<cy.y<<", r="<<cy.radius<<", h="<<cy.height <<"narea="&l

17、t;<cy.area<<", volume="<<cy.volume<<endl; return output;int mainCylinder cy13.5,6.4,5.2,10; cout<<"noriginal cylinder:nx="<<cy1.getX<<", y=" <<cy1.getY<<", r="<<cy1.getRadius<<", h="<&

18、lt; cy1.getHeight<<"narea="<<cy1.area <<", volume="<<cy1.volume<<endl; cy1.setHeight15; cy1.setRadius7.5; cy1.setPoint5,5; cout<<"nnew cylinder:n"<<cy1; Point &pRef=cy1; cout<<"npRef as a point:"<<pRef;

19、 Circle &cRef=cy1; cout<<"ncRef as a Circle:"<<cRef; return 0;original cylinder:x=3.5, y=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虛函數12.

20、3.1虛函數的作用例12.2 基類與派生類有同名函數#include <iostream>#include <string>using namespace std;class Studentpublic: Studentint,string,float; /virtual void display;void display;protected: int num; string name; float score;Student:Studentint n,string nam,float snum=n;name=nam;score=s;void Student:displ

21、aycout<<"num:"<<num<<"nname:"<<name<<"nscore:"<<score<<"nn"class Graduate:public Studentpublic: Graduateint,string,float,float; void display;private: float pay;void Graduate:displaycout<<"num:"<<n

22、um<<"nname:"<<name<<"nscore:"<<score<<"npay="<<pay<<endl;Graduate:Graduateint n,string nam,float s,float p:Studentn,nam,s,paypint mainStudent stud11001,"Li",87.5;Graduate grad12001,"Wang",98.5,563.5;Student *

23、pt=&stud1;pt->display;pt=&grad1;pt->display;return 0;num:1001name:Liscore:87.5num:2001name:Wangscore:98.5假設void display;改為 virtual void display;那么輸出多一行:pay=563.5這種使用virtual修飾的成員函數稱為虛函數。當在派生類中定義了一個同名的成員函數時,只要該成員函數的參數個數和相應類型以及它的返回類型與基類中同名的虛函數完全一樣,那么無論是否為該成員函數使用virtual,它都將成為一個虛函數。使用虛函數保證了

24、在通過一個基類類型的指針包括引用調用一個虛函數時,系統對該調用進展動態關聯,即此時調用的是指針變量指向的對象的同名函數。但是,在通過一對象訪問一虛函數時,那么使用靜態關聯。12.3.2靜態關聯與動態關聯 12.3.3在什么情況下應當聲明虛函數12.3.4虛析構函數例12.3 基類中有非虛析構函數時的執行情況。#include <iostream>using namespace std;class Pointpublic: Pointvirtual Pointcout<<"executing Point destructor"<<endl;

25、class Circle:public Pointpublic:CircleCircle cout<<"executing Circle destructor"<<endl;private:int radus;int mainPoint *p=new Circle;delete p;return 0;executing Point destructor假設將Pointcout<<"executing Point destructor"<<endl;改寫為virtual Pointcout<<&q

26、uot;executing Point destructor"<<endl;那么輸出構造為:executing Circle destructorexecuting Point destructor顯然這是我們想要的結果,因此,為了使用動態內存new delete,應將基類的析構函數聲明為虛析構函數。12.4純虛函數與抽象類12.4.1純虛函數virtual float area const return 0;/空虛函數virtual float area const =0;/純虛函數純虛函數沒有函數體,也沒有給它分配內存。它的定義留給派生類來做。12.4.2抽象類一個類

27、可以說明多個純虛函數,包含有純虛函數的類稱為抽象類。一個抽象類只能作為基類來派生新類,不能說明抽象類的對象。說明了純虛函數的派生類仍是抽象類。假設派生類中給出了基類所有純虛函數的實現,那么該派生類不再是抽象類。/使用純虛函數的例子。#include<iostream.h>class numberprotected: int val;public: numberint ival = i; virtual void show = 0;class hextype : public numberpublic: hextypeint i : numberi void showcout<

28、<hex<<val<<dec<<endl;class dectype : public numberpublic:dectypeint i : numberivoid showcout<<dec<<val<<endl;void mainnumber *nump;dectype d56;nump=&d;nump->show;hextype h15;nump=&h;nump->show;56f12.4.3應用實例例12.4 虛函數和抽象基類的應用。#include <iostream&g

29、t;using namespace std;/聲明抽象基類Shapeclass Shapepublic: virtual float area const return 0.0;/虛函數 virtual float volume const return 0.0;/虛函數 virtual void shapeName const =0;/純虛函數;/聲明Point類 Point是Shape的公用派生類class Point:public Shape public: Pointfloat=0,float=0; void setPointfloat,float; float getX const

30、return x; float getY const return y; virtual void shapeName const cout<<"Point:" /對純虛函數進展定義 friend ostream & operator<<ostream &,const Point &protected: float x,y;Point:Pointfloat a,float bx=a;y=b;void Point:setPointfloat a,float bx=a;y=b;ostream & operator<&

31、lt;ostream &output,const Point &poutput<<""<<p.x<<","<<p.y<<"" return output;/聲明Circle類class Circle:public Pointpublic: Circlefloat x=0,float y=0,float r=0; void setRadiusfloat; float getRadius const; virtual float area const; virtu

32、al void shapeName const cout<<"Circle:" /對純虛函數進展再定義 friend ostream &operator<<ostream &,const Circle & protected: float radius;Circle:Circlefloat a,float b,float r :Pointa,b,radiusrvoid Circle:setRadiusfloat rradius=r;float Circle:getRadius const return radius;float

33、 Circle:area constreturn 3.14159*radius*radius;ostream &operator<<ostream &output,const Circle &coutput<<""<<c.x<<","<<c.y<<", r="<<c.radius; return output;/聲明Cylinder類class Cylinder:public Circlepublic: Cylinder flo

34、at x=0,float y=0,float r=0,float h=0; void setHeightfloat; float getHeight const; virtual float area const; virtual float volume const; virtual void shapeName const cout<<"Cylinder:" /對純虛函數進展再定義 friend ostream& operator<<ostream&,const Cylinder& protected: float hei

35、ght;Cylinder:Cylinderfloat a,float b,float r,float h :Circlea,b,r,heighthvoid Cylinder:setHeightfloat hheight=h;float Cylinder:getHeight const return height;float Cylinder:area const return 2*Circle:area+2*3.14159*radius*height;float Cylinder:volume constreturn Circle:area*height;ostream &operat

36、or<<ostream &output,const Cylinder& cyoutput<<""<<cy.x<<","<<cy.y<<", r="<<cy.radius <<", h="<<cy.height; return output;int mainPoint point3.2,4.5; /建立Point類對象point Circle circle2.4,12,5.6;/建立Circle

37、類對象circle Cylinder cylinder3.5,6.4,5.2,10.5;/建立Cylinder類對象cylinder point.shapeName;/靜態關聯 cout<<point<<endl; circle.shapeName;/靜態關聯 cout<<circle<<endl; cylinder.shapeName;/靜態關聯 cout<<cylinder<<endl<<endl; Shape *pt; /定義基類指針 pt=&point; /指針指向Point類對象 pt->

38、;shapeName; /動態關聯 cout<<"x="<<point.getX<<",y="<<point.getY<<"narea=" <<pt->area<<"nvolume="<<pt->volume<<"nn" pt=&circle; /指針指向Circle類對象 pt->shapeName; /動態關聯 cout<<"x=&quo

39、t;<<circle.getX<<",y="<<circle.getY<<"narea=" <<pt->area<<"nvolume="<<pt->volume<<"nn" pt=&cylinder; /指針指向Cylinder類對象 pt->shapeName;/動態關聯 cout<<"x="<<cylinder.getX<<"

40、,y="<<cylinder.getY<< "narea="<<pt->area<<"nvolume="<<pt->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=0Circle:x=2.4,y=12area=98.5203volume=0Cylinder:x=

41、3.5,y=6.4area=512.959volume=891.96例編寫一個用于計算各類形狀的總面積的例子。這個程序用于計算各類形狀的總面積。由于尚不能確定該程序處理的詳細形狀,我們先定義一個抽象的shape類。/shape.hclass shape public: virtual float area=0;float totalshape *s,int n;有了shape類,就可以開場設計求面積程序:/shape.cpp#include "shape.h"#include <iostream.h>float totalshape * s ,int nfloa

42、t sum = 0;forint i=0;i<n;i+sum+=si->area;cout<<si->area<<endl;return sum;該程序可以用于求各類形狀的面積之和。對于詳細種類的形狀,通過從shape派生一個類來對其進展描繪,以重用上面的代碼,并且不用重新對這些碼進展編譯。也就是說,可以把函數total放在一個程序庫中,以便其它程序在需要使用。例如:#include<iostream.h>#include"shape.h"class triangle : public shapeprotected :

43、float H , W;public:trianglefloat h , float w H = h ; W = w ;float area return H * W * 0.5 ; ;class rectangle :public triangle public :rectanglefloat h, float w :triangleh,w float area return H * W ;class circle : public shape protected : float radius ;public : circlefloat r radius = r; float arearet

44、urn radius * radius * 3.14; ;void mainshape *s4 ;s0 = new triangle3.0,4.0;s1 = new rectangle2.0,4.0 ;s2 = new circle5.0 ;s3 = new circle8.0 ;float sum = totals,4 ;cout << sum<<endl;delete s0;delete s1;delete s2;delete s3;在該例中,shape類中的虛函數area僅起到為派生類提供一個一致的接口的作用,派生類中重定義的area 用于決定以什么的方式計算面積

45、。由于在shape類中不能對此作用決定,因此被說明為純虛函數。從此例子可以看出,賦值兼容規那么使我們可將正方形、三角形、圓都視為形狀,多態性又保證了函數total在對各種形狀求面積之和時,無須關心當前正在計算哪種詳細形狀的面積。在需要時,函數total可從這些形狀的對象那里獲得該對象的面積,成員函數area保證了這點。特別聲明:最好使用虛析構函數。#include <iostream.h>class shape public: virtual float area=0; virtual shapecout<<"del shapen"float tot

46、alshape * s ,int nfloat sum = 0;forint i=0;i<n;i+sum+=si->area;cout<<si->area<<endl;return sum;class triangle : public shapeprotected : float H , W;public:trianglefloat h , float w H = h ; W = w ;float area return H * W * 0.5 ; trianglecout<<"del trianglen"class

47、rectangle :public triangle public :rectanglefloat h, float w :triangleh,w rectanglecout<<"del rectanglen"float area return H * W ;class circle : public shape protected : float radius ;public : circlefloat r radius = r;circlecout<<"del circlen" float areareturn radius

48、* radius * 3.14; ;void mainshape *s4 ;s0 = new triangle3.0,4.0;s1 = new rectangle2.0,4.0 ;s2 = new circle5.0 ;s3 = new circle8.0 ;float sum = totals,4 ;cout << sum<<endl;delete s0;delete s1;delete s2;delete s3;6878.5200.96293.46del triangledel shapedel rectangledel triangledel shapedel c

49、ircledel shapedel circledel shape實驗:1:實驗目的:1理解多態性的概念。2理解虛函數的作用及使用方法。3理解靜態關聯和動態關聯的概念和用法。4理解純虛函數和抽象類的概念和用法。2:實驗內容: P416 1 43:實驗結果。下面是虛析構函數的真正用處例子,供有興趣同學參考。數據庫中保存各類對象的例子。/database.hclass object public:virtual int isEqualobject&=0;virtual object;class database private:object* rec100;int pc,iterPc; p

50、ublic:databasepc=iterPc=0;int addobject&object* read;void rewinditerPc=0;int GetPcreturn pc;int GetIterpcreturn iterPc;database;database類的成員函數add用于向數據庫中增添一個對象,read 對數據庫進展順序讀,并返回讀到的每一個對象,當所有對象被讀完時,返回0。為使同一個對象在數據庫中不保存兩個備份,add要將欲參加的對象與數據庫中的對象進展相等比較,object類中的成員函數isEqual用于比較對象,當兩個對象相等時,它返回1。因為在沒有明確詳細

51、種類的對象之前,無法給出isEqual的定義,所以,它被說明為純虛函數。/database.cpp#include"database.h"int database : addobject& obj for int i=0;i<pc;i+ifreci->isEqualobjreturn 0;recpc+=&obj;return 1;object * database : read ifiterPc < pc return reciterPc+; else return 0;database : databaseforint i=0;i<

52、pc;i+delete reci;下面是使用這個程序的例如程序。/univ.h#include<iostream.h>#include<string.h>#includedatabase.hclass person : public objectprotected: char * name; personname=0;public:personchar *sname=new charstrlens+1;strcpyname,s;virtual void print=0;int isEqualobject& objperson& man=person&am

53、p;obj;return strcmpname, =0;persondelete name;class student : virtual public person private: int val; public: studentchar * s,int l:personsval=l; void printcout<<name<<" "<<val<<endl;class univDBase : public database public: person* read returnperson *databa

54、se : read;測試程序是:#includeuniv.hvoid mainunivDBase univ;univ.add * new student"Zhang",3;univ.add * new student"Li",4;univ.add * new student"Wang",5;person * p;whilep=univ.read!=0p->print;univ.rewind;whilep=univ.read!=0p->print; 讀者分析一下該程序中虛析構函數的作用。假設不使用虛析構函數,在程序完畢時,p

55、erson類的成員name所指向的一段內存就不能釋放。另外應注意,從databade類派生univDBase類目的是為交換database類的接口:使read返回一個person類類型的指針,這樣,main函數就比較明晰可讀。由于目前數據庫中只保存person類的對象,所以,在函數read中進展強迫類型轉換是平安的。從這個程序可以看出,基類定義了比派生類更大的對象集合,因此,基于基類所做的抽象所設計的程序必然可以用于派生類這種詳細情形。將多個類中的共性抽象到基類中以便重用代碼,這是面向對象和程序設計方法的一個重要思想,多態性從語言的實現上為代碼重用提供了有力的支持。測試實例:#include&

56、lt;iostream.h>#include<string.h>/#include"database.h"class object public:virtual int isEqualobject&=0;virtual objectcout<<"object"<<endl;class database private:object* rec100;int pc,iterPc; public:databasepc=iterPc=0;int addobject&object* read;void re

57、winditerPc=0;int GetPcreturn pc;int GetIterpcreturn iterPc;database;int database : addobject& obj for int i=0;i<pc;i+ifreci->isEqualobjreturn 0;recpc+=&obj;return 1;object * database : read/cout<<"database read "<<pc<<" "<<iterPc<<endl;

58、ifiterPc < pccout<<"fff database read "<<pc<<" "<<iterPc<<endl;return reciterPc+;else cout<<"end database read "<<pc<<" "<<iterPc<<endl; return 0;database : databaseforint i=0;i<pc;i+delete reci;class person : public objectprotected: char * name; personname=0;public:personchar *sname=new charstrlens+1;strcpyname,

溫馨提示

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

評論

0/150

提交評論