c++面向?qū)ο蟪绦蛟O計第5版_第1頁
已閱讀1頁,還剩54頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、C++面向?qū)ο蟪绦蛟O計(第5版),浙江工業(yè)大學 軟件學院,,國外經(jīng)典教材.計算機科學與技術(shù) (美) Walter Savitch,第5章 多態(tài)性與虛函數(shù),5.1 多態(tài)性的概念5.2 一個典型的例子5.3 虛函數(shù)5.4 純虛函數(shù)與抽象類,5.1 多態(tài)性的概念,在C++中,基類指針或引用可以直接引用其任何派生子 類,而無需程序員介入——這種“用基類的指針或引用操縱多個類型”的能力稱為多態(tài)

2、(polymorphism)。多態(tài)性(polymorphism)是面向?qū)ο蟪绦蛟O 計的一個重要特征。利用多態(tài)性可以設計和實現(xiàn)一個易于擴展的系統(tǒng)。,,例如,已知基類Camera派生出兩個子類OrthographicCamera和PerspectiveCamera:已知函數(shù): void lookAt( const Camera *pcamera );,Camera,Perspectiv

3、eCamera,OrthographicCamera,,每次lookAt()函數(shù)調(diào)用時都會傳入一個Camera子類對象的地址,編譯器會自動地把它轉(zhuǎn)換成適當?shù)幕愔羔?。例如:OrthographicCamera ocam;lookAt( &ocam ); //ok:自動轉(zhuǎn)換成 Camera*PerspectiveCamera *pcam = new PerspectiveCamera;lookAt( pcam

4、); //ok:自動被轉(zhuǎn)換成Camera*lookAt()的實現(xiàn)被屏蔽在應用程序的實際Camera子類之外,如果以后增加或刪除一個子類,無需改變lookAt().子類多態(tài)性使得我們在編寫應用程序的核心時,可以不用考慮將來需要維護的單個類型。,,從系統(tǒng)實現(xiàn)的角度看,多態(tài)性分為兩類: 靜態(tài)多態(tài)性和動態(tài)多態(tài)性。靜態(tài)多態(tài)性是通過函數(shù)的重載實現(xiàn)的。利用基類指針和引用,對抽象基類的公有接口進行編程。在運行時刻,真正要引用的類型被解析出來

5、,并且調(diào)用適當?shù)墓薪涌趯嵗?。多態(tài)性是“一個接口,多種方法”。在運行時刻解析出被調(diào)用的函數(shù),這個解析過程被稱為動態(tài)綁定(dynamic binding)。在C++中,通過虛擬函數(shù)機制來支持動態(tài)綁定。通過繼承和動態(tài)綁定,子類型多態(tài)性為面向?qū)ο蟮某绦蛟O計提供了基礎。,5.2 一個典型的例子,下面是一個承上啟下的例子。一方面它是有關繼承和運算符重載內(nèi)容的綜合應用的例子,通過這個例子可以進一步融會貫通前面所學的內(nèi)容,另一方面又是作為討論

6、多態(tài)性的一個基礎用例。例5.1: 先建立一個Point(點)類,包含數(shù)據(jù)成員x,y(坐標點)。以它為基類,派生出一個Circle(圓)類,增加數(shù)據(jù)成員r(半徑),再以Circle類為直接基類,派生出一個Cylinder(圓柱體)類,再增加數(shù)據(jù)成員h(高)。要求編寫程序,重載運算符“>”,使之能用于輸出以上類對象。,,聲明基類Point類可寫出聲明基類Point的部分如下:#include //聲明類Pointcla

7、ss Point{ public: Point(float x=0,float y=0);//有默認參數(shù)的構(gòu)造函數(shù) void setPoint(float,float); //設置坐標值float getX( ) const {return x;} //讀x坐標 float getY( ) const {return y;}

8、 //讀y坐標friend ostream & operator<<(ostream &,const Point &);//重載運算符“<<” protected: //受保護成員 float x,y;};,,//下面定義Point類的成員函數(shù)//Point的構(gòu)造函數(shù)Point::Poin

9、t(float a,float b) //對x,y初始化{x=a;y=b;}//設置x和y的坐標值void Point::setPoint(float a,float b) //為x,y賦新值{x=a;y=b;}//重載運算符“<<”,使之能輸出點的坐標ostream & operator<<(ostream &output,cons

10、t Point &p){output<<″[″<<p.x<<″,″<<p.y<<″]″<<endl; return output;},,編寫測試程序main函數(shù):int main( ){ Point p(3.5,5.4); //建立Point類對象p cout<<″x=″<<p.getX( )&

11、lt;<″,y=″<<p.getY( )<<endl; //輸出p的坐標值 p.setPoint(8.5,5.8); //重新設置p的坐標值 cout<<″p(new):″<<p<<endl; //用重載運算符“<<”輸出p點坐標}程序編譯通過,運行結(jié)果

12、為 x=3.5,y=5.4 p(new):[8.5,5.8]測試程序檢查了基類中各函數(shù)的功能,以及運算符重載的作用,證明程序是正確的。,,(2) 聲明派生類Circleclass Circle : public Point //circle是Point類的公用派生類{ public: Circle(float x=0,float y=0,float r=0); //構(gòu)造函數(shù)

13、 void setRadius(float); //設置半徑值 float getRadius( ) const; //讀取半徑值float area ( ) const; //計算圓面積 friend ostream &operator<<(ostream &,const Cir

14、cle &); //重載運算符“<<” private: float radius;};,,//定義構(gòu)造函數(shù),對圓心坐標和半徑初始化Circle::Circle(float a,float b,float r):Point(a,b),radius(r){ }//設置半徑值void Circle::setRadius(float r){radius=r;}

15、//讀取半徑值float Circle::getRadius( ) const {return radius;}//計算圓面積float Circle::area( ) const{return 3.14159*radius*radius;}//重載運算符“<<”,使之按規(guī)定的形式輸出圓的信息ostream &operator<<(ostream &output,const C

16、ircle &c){ output<<″Center=[″<<c.x<<″,″<<c.y<<″],r=″<<c.radius<<″,area =″<<c.area( )<<endl; return output;},,測試Circle類定義的主函數(shù):int main( ){

17、 Circle c(3.5,5.4,5.2);//建立Circle類對象c,并給定圓心坐標和半徑 cout<<″original circle:\\nx=″<<c.getX()<<″, y=″<<c.getY() <<″, r=″<<c.getRadius( ) <<″, area=″<<c.area(

18、)<<endl; //輸出圓心坐標、半徑和面積 c.setRadius(7.5); //設置半徑值 c.setPoint(5,5); //設置圓心坐標值x,y cout<<″new circle:\\n″<<c; //用重載運算符“<<”輸出圓對象

19、的信息 Point &pRef=c; //pRef是Point類的引用變量,被c初始化 cout<<″pRef:″<<pRef; //輸出pRef的信息 return 0;}程序編譯通過,運行結(jié)果為:original circle:x=3.5, y=5.4, r=5.2, area=84.94

20、85new circle: Center=[5,5], r=7.5, area=175.714pRef:[5,5],,(3) 聲明Circle的派生類Cylinderclass Cylinder:public Circle// Cylinder是Circle的公用派生類{ public: Cylinder (float x=0,float y=0,flo

21、at r=0,float h=0);void setHeight(float); //設置圓柱高 float getHeight( ) const; //讀取圓柱高 float area( ) const; //計算圓表面積 float volume( ) const;

22、 //計算圓柱體積 friend ostream& operator<<(ostream&,const Cylinder&); protected: float height; //圓柱高};,,//定義構(gòu)造函數(shù)Cylinder::Cylinder(float a,float

23、 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*C

24、ircle::area( )+2*3.14159*radius*height;}//計算圓柱體積float Cylinder::volume() const{return Circle::area()*height;}//重載運算符“<<”ostream &operator<<(ostream &output,const Cylinder& cy){output<&l

25、t;″Center=[″<<cy.x<<″,″<<cy.y<<″],r=″<<cy.radius<<″,h=″<<cy.height <<″\\narea=″<<cy.area( )<<″, volume=″<<cy.volume( )<<endl; return output;

26、},,寫出下面的測試主函數(shù): int main( ){Cylinder cy1(3.5,5.4,5.2,10);//定義Cylinder類對象cy1 cout<<″\\noriginal cylinder:\\nx=″<<cy1.getX( ) <<″,y=″<<cy1.getY( )<<″, r=″ <<

27、cy1.getRadius( )<<″,h=″<<cy1.getHeight( ) <<″\\narea=″<<cy1.area() <<″,volume=″<<cy1.volume()<<endl;//用系統(tǒng)定義的運算符“<<”輸出cy1的數(shù)據(jù) cy1.setHeight(15);

28、 //設置圓柱高 cy1.setRadius(7.5); //設置圓半徑 cy1.setPoint(5,5); //設置圓心坐標值x,y cout<<″\\nnew cylinder:\\n″<<cy1; //用重載運算符“<<”輸出cy1的數(shù)據(jù) Point &pRef=cy1;

29、 //pRef是Point類對象的引用變量cout<<″\\npRef as a Point:″<<pRef; //pRef作為一個“點”輸出 Circle &cRef=cy1; //cRef是Circle類對象的引用變量 cout<<″\\ncRef as a Circle:″<

30、<cRef; //cRef作為一個“圓”輸出 return 0;},,運行結(jié)果如下:original cylinder: (輸出cy1的初始值)x=3.5, y=5.4, r=5.2, h=10 (圓心坐標x,y。半徑r,高h)area=495.523, volume=849.485 (圓柱表面積area和體積volume

31、)new cylinder: (輸出cy1的新值)Center=[5,5], r=7.5, h=15 (以[5,5]形式輸出圓心坐標)area=1050.29, volume=2550.72 (圓柱表面積area和體積volume)pRef as a Point:[5,5] (pRef作為

32、一個“點”輸出)cRef as a Circle: Center=[5,5], r=7.5, area=175.714(cRef作為一個“圓”輸出)在本例中存在靜態(tài)多態(tài)性,這是運算符重載引起的。可以看到,在編譯時編譯系統(tǒng)即可以判定應調(diào)用哪個重載運算符函數(shù)。,5.3 虛函數(shù) 5.3.1 虛函數(shù)的作用,在類的繼承層次結(jié)構(gòu)中,在不同的層次中可以出現(xiàn)名字相同、參數(shù)個數(shù)和類型都相同而功能不同的函數(shù)。編譯系統(tǒng)按照同名覆蓋的原則決定調(diào)用的

33、對象。例如:例5.1程序中cy1.area( )調(diào)用的是派生類Cylinder中的成員函數(shù)area。如果想調(diào)用cy1中的直接基類Circle的area函數(shù),改如何調(diào)用呢?應當表示為: cy1.Circle::area( )。用這種方法來區(qū)分兩個同名的函數(shù)很不方便。,,能否用同一個調(diào)用形式,既能調(diào)用派生類又能調(diào)用基類的同名函數(shù)?可以在程序中通過指針調(diào)用基類和派生類的同名函數(shù),根據(jù)指針實際指向的對象來調(diào)用對應的函數(shù)。例如,語句

34、pt->display( ); 可以調(diào)用不同派生層次中的display函數(shù),只需在調(diào)用前給指針變量pt賦以不同的值(使之指向不同的類對象)即可。C++通過虛函數(shù)來解決這個問題。虛函數(shù)的作用是允許在派生類中重新定義與基類同名的函數(shù),并且可以通過基類指針或引用來訪問基類和派生類中的同名函數(shù)。我們來分析例5.2。這個例子開始時沒有使用虛函數(shù),然后再討論使用虛函數(shù)的情況。,,例5.2 基類Student與派生類Graduate有同

35、名函數(shù)。#include #include using namespace std;//聲明基類Studentclass Student{ public: Student(int, string,float); //聲明構(gòu)造函數(shù) void display( ); /聲明輸出函數(shù) protected:

36、 //受保護成員,派生類可以訪問 int num; string name; float score; };,,//Student類成員函數(shù)的實現(xiàn)Student::Student(int n, string nam,float s) //定義構(gòu)造函數(shù) {num=n;name=nam;score=s;}void Student::d

37、isplay( ) //定義輸出函數(shù){cout<<″num:″<<num<<″\\nname:″<<name<<″\\nscore:″<<score<<″\\n\\n″;},,//聲明公用派生類Graduateclass Graduate:public Student{p

38、ublic: Graduate(int, string, float, float); //聲明構(gòu)造函數(shù) void display( ); //聲明輸出函數(shù)private: float pay;};// Graduate類成員函數(shù)的實現(xiàn)Graduate::Graduate(int n, stri

39、ng nam,float s,float p):Student(n,nam,s),pay(p){ }void Graduate::display( ) //定義輸出函數(shù){cout<<″num:″<<num<<″\\nname:″<<name<<″\\nscore:″<<score<<″

40、\\npay=″<<pay<<endl;},,//主函數(shù)int main(){Student stud1(1001, “Li”, 87.5);Graduate grad1(2001, “Wang”, 98.5, 563.5); Student *pt = &stud1;pt->display();pt = &grad1;pt->displ

41、ay();return 0;},,運行結(jié)果如下,請仔細分析。num:1001name:Liscore:87.5num:2001 name:wangscore:98.5,,對程序作一點修改,在Student類中聲明display函數(shù)時,在最左面加一個關鍵字virtual,即 virtual void display( );再編譯和運行程

42、序,請注意分析運行結(jié)果: num:1001name:Liscore:87.5num:2001 name:wangscore:98.5pay=1200,5.3.2 C++中的虛函數(shù),假定我們要為汽車零件商店設計一個記帳程序。希望該程序非常靈活,能夠兼容以后出現(xiàn)的新銷售情況。為了適應這種情況,將計算賬單的函數(shù)設為虛函數(shù)。設計基類Sale, Sale類對應于單件商品的簡單銷售。所有類型的銷售(如打折銷售)都是Sale類

43、的派生類。,,由虛函數(shù)實現(xiàn)的動態(tài)多態(tài)性就是:基類的指針或引用可以指向其任意派生類的能力。虛函數(shù)的使用方法是: 在基類用virtual聲明成員函數(shù)為虛函數(shù)。在派生類中重新定義此函數(shù),要求函數(shù)名、函數(shù)類型、函數(shù)參數(shù)個數(shù)和類型全部與基類的虛函數(shù)相同,并根據(jù)派生類的需要重新定義函數(shù)體。定義一個指向基類對象的指針變量,并使它指向同一類繼承層次結(jié)構(gòu)中的某個對象。通過該指針變量調(diào)用此虛函數(shù),此時調(diào)用的就是指針變量指向的對象的同名函數(shù)。,,C

44、++規(guī)定,當一個成員函數(shù)被聲明為虛函數(shù)后,其派生類中的同名函數(shù)都自動成為虛函數(shù)。在派生類重新聲明該虛函數(shù)時,可以加virtual,也可以不加,但習慣上一般在每一層聲明該函數(shù)時都加virtual,使程序更加清晰。如果在派生類中沒有對基類的虛函數(shù)重新定義,則派生類簡單地繼承其直接基類的虛函數(shù)。特別提醒:有時在基類中定義的非虛函數(shù)會在派生類中被重新定義(如例5.1中的area函數(shù)),此時不存在多態(tài)性。,5.3.3 靜態(tài)關聯(lián)與動態(tài)關聯(lián),計

45、算機系統(tǒng)如何選擇正確的調(diào)用對象,從而實現(xiàn)多態(tài)性?確定調(diào)用的具體對象的過程稱為關聯(lián)(binding)。在這里是指把一個函數(shù)名與一個類對象捆綁在一起,建立關聯(lián)。一般地說,關聯(lián)指把一個標識符和一個存儲地址聯(lián)系起來。靜態(tài)關聯(lián)(static binding)和動態(tài)關聯(lián)(dynamic binding)(晚期綁定),,在編譯時即可確定其調(diào)用的函數(shù)屬于哪一個類,其過程稱為靜態(tài)關聯(lián)(static binding),又稱為早期關聯(lián)(early bin

46、ding)。函數(shù)重載屬靜態(tài)關聯(lián)。 對于通過基類指針調(diào)用虛函數(shù),編譯系統(tǒng)在編譯該行時是無法確定調(diào)用哪一個類對象的虛函數(shù)的。在這樣的情況下,在運行階段確定關聯(lián)關系。此過程稱為動態(tài)關聯(lián)(dynamic binding)。這種多態(tài)性是運行階段的多態(tài)性。在運行階段,指針可以先后指向不同的類對象,從而調(diào)用同一類族中不同類的虛函數(shù)。由于動態(tài)關聯(lián)是在編譯以后的運行階段進行的,因此也稱為晚期關聯(lián)(late binding)。,5.3.4 在什么情況

47、下應當聲明虛函數(shù),使用虛函數(shù)時,有兩點要注意: (1)虛函數(shù)只能作用于類的繼承層次結(jié)構(gòu)中,即多態(tài)性只存在于類繼承層次中。(2) 一個成員函數(shù)被聲明為虛函數(shù)后,在同一類族中的類就不能再定義一個非virtual的但與該虛函數(shù)具有相同的參數(shù)(包括個數(shù)和類型)和函數(shù)返回值類型的同名函數(shù)。,,根據(jù)什么考慮是否把一個成員函數(shù)聲明為虛函數(shù)呢?主要考慮以下幾點: (1) 首先看成員函數(shù)所在的類是否會作為基類。然后看成員函數(shù)在類的繼承后有無可能被更

48、改功能,如果希望更改其功能的,一般應該將它聲明為虛函數(shù)。(2) 如果成員函數(shù)在類被繼承后功能不需修改,或派生類用不到該函數(shù),則不要把它聲明為虛函數(shù)。,,(3) 應考慮對成員函數(shù)的調(diào)用是通過對象名還是通過基類指針或引用去訪問,如果是通過基類指針或引用去訪問的,則應當聲明為虛函數(shù)。(4) 有時會在基類定義具有空函數(shù)體的虛函數(shù)。它的作用只是定義了一個虛函數(shù)名(即公有接口),然后通過派生類來添加具體功能。在5.4節(jié)中將詳細討論此問題。(5

49、)編譯器和運行環(huán)境需要為虛函數(shù)做較多的工作,所以,如果將不必要設置為虛函數(shù)的函數(shù)標記為virtual,會影響程序的執(zhí)行效率。,5.3.5 虛析構(gòu)函數(shù),繼承機制下的析構(gòu)函數(shù)的行為如下:派生類的析構(gòu)函數(shù)先被調(diào)用。完成之后,直接基類的析構(gòu)函數(shù)被靜態(tài)調(diào)用。但是,如果用new運算符建立了臨時對象,若基類中有析構(gòu)函數(shù),并且定義了一個指向該基類的指針變量。在程序用帶指針參數(shù)的delete運算符撤銷對象時,會發(fā)生一個情況: 系統(tǒng)會只執(zhí)行基類的析構(gòu)函數(shù)

50、,而不執(zhí)行派生類的析構(gòu)函數(shù)。,,例5.3 基類中有非虛析構(gòu)函數(shù)時的執(zhí)行情況。(為簡化程序,只列出最必要的部分。)#include using namespace std;class Point//定義基類Point類{public: Point( ){ } //Point類構(gòu)造函數(shù) ~Point(){cout<<

51、;″executing Point destructor″<<endl;}//Point類析構(gòu)函數(shù)};class Circle:public Point //定義派生類Circle類{public: Circle( ){ } //Circle類構(gòu)造函

52、數(shù) ~Circle( ){cout<<″executing Circle destructor″<<endl;}//Circle類析構(gòu)函數(shù) private: int radius;};int main( ){ Point *p=new Circle; //用new開辟動態(tài)存儲空間delete p;

53、 //用delete釋放動態(tài)存儲空間return 0;},,運行結(jié)果為:executing Point destructor表示只執(zhí)行了基類Point的析構(gòu)函數(shù),而沒有執(zhí)行派生類Circle的析構(gòu)函數(shù)。為了執(zhí)行派生類Circle的析構(gòu)函數(shù),需要將基類的析構(gòu)函數(shù)聲明為虛析構(gòu)函數(shù),即 virtual ~Point(){cout<<″executing Point

54、 destructor″<<endl;}程序其他部分不改動,再運行程序,結(jié)果為executing Circle destructorexecuting Point destructor,,如果將基類的析構(gòu)函數(shù)聲明為虛函數(shù)時,由該基類所派生的所有派生類的析構(gòu)函數(shù)也都自動成為虛函數(shù),即使派生類的析構(gòu)函數(shù)與基類的析構(gòu)函數(shù)名字不相同。最好把基類的析構(gòu)函數(shù)聲明為虛函數(shù)。這將使所有派生類的析構(gòu)函數(shù)自動成為虛函數(shù)。

55、構(gòu)造函數(shù)不能聲明為虛函數(shù)。這是因為在執(zhí)行構(gòu)造函數(shù)時類對象還未完成建立過程,當然談不上函數(shù)與類對象的綁定。,5.4 純虛函數(shù)與抽象類 5.4.1 純虛函數(shù),C++語言提供了一種語法結(jié)構(gòu),通過它表明,一個虛擬函數(shù)只是提供了一個可被派生子類型改寫的接口,它本身并不能通過虛擬機制被調(diào)用——純虛擬函數(shù)例如在例5.1程序中,基類Point可以提供求面積的純虛擬函數(shù):virtual float area( ) const =0;//純虛函

56、數(shù)其直接派生類Circle和間接派生類Cylinder可以改寫這個area函數(shù),分別為求圓面積和求圓柱體表面積。,,純虛函數(shù)是在聲明虛函數(shù)時被“初始化”為0的函數(shù)。聲明純虛函數(shù)的一般形式是virtual 函數(shù)類型 函數(shù)名 (參數(shù)表列) =0;注意: ①純虛函數(shù)沒有函數(shù)體;②最后面的“=0”并不表示函數(shù)返回值為0,它只起形式上的作用,告訴編譯系統(tǒng)“這是純虛函數(shù)”;③這是一個聲明語句,最后應有分號。,5.4.2 抽象類

57、,包含一個或多個純虛函數(shù)的類稱為抽象基類(abstract class)。試圖創(chuàng)建一個抽象基類的獨立類對象會導致編譯錯誤。抽象類的作用是作為一個類繼承層次結(jié)構(gòu)的共同基類,或者說,為一個類繼承層次結(jié)構(gòu)提供一個公共接口。這種類不用來定義對象,一般只作為一種被繼承的基本類型。如果在派生類中對基類的所有純虛函數(shù)進行了定義,那么這些函數(shù)就被賦予了功能,可以被調(diào)用。這時派生類是可以用來定義對象的具體類(concrete class);否則

58、派生類仍然是抽象類,不能用來定義對象。我們可以定義指向抽象類對象的指針變量,用此指針指向具體派生類的對象,然后通過該指針調(diào)用虛函數(shù),實現(xiàn)多態(tài)性的操作。,5.4.3 應用實例,例5.4 虛函數(shù)和抽象基類的應用。在例5.1介紹了以Point為基類的點—圓—圓柱體類的層次結(jié)構(gòu)。現(xiàn)在對它進行改寫,在程序中使用虛函數(shù)和抽象基類。類的層次結(jié)構(gòu)的頂層是抽象基類Shape(形狀)。Point(點), Circle(圓), Cylinder(圓柱體

59、)都是Shape類的直接派生類和間接派生類。程序如下:,第(1)部分#include using namespace std;//聲明抽象基類Shapeclass Shape{ public: virtual float area( ) const {return 0.0;} virtual float volume() const {return 0.0;} virtual void shapeName(

60、) const =0; };,,第(2)部分//聲明Point類class Point : public Shape//Point是Shape的公用派生類{ public: Point(float=0,float=0); void setPoint(float,float); float getX( ) const {return x;} float getY( ) c

61、onst {return y;} virtual void shapeName( ) const {cout<<″Point:″;} //對虛函數(shù)進行再定義 friend ostream & operator<<(ostream &,const Point &); protected: f

62、loat x,y;};,,//定義Point類成員函數(shù)Point::Point(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){output<<″[″<<

63、;p.x<<″,″<<p.y<<″]″;return output;},,第(3)部分//聲明Circle類class Circle : public Point{ public: Circle(float x=0,float y=0,float r=0); void setRadius(float); float getRadius( ) const

64、; virtual float area( ) const; virtual void shapeName( ) const {cout<<″Circle:″;}//對虛函數(shù)進行再定義 friend ostream &operator<<(ostream &,const Circle &); protected: float radius;};,,/

65、/聲明Circle類成員函數(shù)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 {return 3.14159

66、*radius*radius;}ostream &operator<<(ostream &output,const Circle &c){output<<″[″<<c.x<<″,″<<c.y<<″], r=″<<c.radius; return output;},,第(4)部分//聲明Cylinder類clas

67、s Cylinder : public Circle{ public: Cylinder (float x=0,float y=0,float r=0,float h=0); void setHeight(float); virtual float area( ) const; virtual float volume( ) const; virtual void shapeName( ) con

68、st {cout<<″Cylinder:″;}//對虛函數(shù)進行再定義 friend ostream& operator<<(ostream&,const Cylinder&); protected: float height;};,,//定義Cylinder類成員函數(shù)Cylinder::Cylinder(float a,float b,float r,float

69、 h) :Circle(a,b,r),height(h){ }void Cylinder::setHeight(float h){height=h;}float Cylinder::area( ) const{ return 2*Circle::area( )+2*3.14159*radius*height;}float Cylinder::volume( ) const{return Circle::area(

70、 )*height;}ostream &operator<<(ostream &output,const Cylinder& cy){output<<″[″<<cy.x<<″,″<<cy.y<<″], r=″<<cy.radius<<″, h=″<<cy.height;return outpu

71、t;},,第(5)部分//main函數(shù)int main( ){Point point(3.2,4.5);//建立Point類對象point Circle circle(2.4,1.2,5.5); //建立Circle類對象circle Cylinder cylinder(3.5,5.4,5.2,10.5); //建立Cylinder類對象cylinder poi

72、nt.shapeName(); //靜態(tài)關聯(lián) coutshapeName( ); //動態(tài)關聯(lián) coutarea( ) volume()<<″\\n\\n″; pt=&circle; //指針指向Circle類

溫馨提示

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

評論

0/150

提交評論