版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、總84頁1Part four繼承與派生繼承與派生總84頁2一、為什么要使用繼承一、為什么要使用繼承l(wèi)繼承是一個非常自然的概念l所謂繼承就是從先輩處得到屬性和行為特征。l類的繼承和派生機制是程序員無需修改已有類,只需在已有類的基礎上增加少量代碼或修改少量代碼的方法得到新的類,減少了程序員的工作量,并增加了代碼的重用率???4頁3 在C+中,可以利用已有的類來定義新的類,新類將擁有原有類的全部特性,原有類被稱為基類基類(Base class)或父類(Super class),新產(chǎn)生的類被稱為派生類派生類(Derived class)或子類(Sub class)。派生類擁有基類的特性稱作繼繼承承,由
2、基類產(chǎn)生派生類的過程稱為派生派生。 每一個派生類都有且僅有一個基類,派生類可以看作是基類的特例,它增加了某些基類所沒有的性質(zhì)。這種繼承方式,稱為單繼承單繼承或單向繼承。 現(xiàn)實生活中,子女的外貌、血型往往不是僅僅繼承自父親或母親,而是將父母親的特點都繼承下來。與之相類似,如果一個派生類有兩個或兩個以上的基類,則稱為多繼承多繼承或多重繼承。 二、繼承的概念二、繼承的概念總84頁4 派生類又作為基類,繼續(xù)派生新的類, 這樣的派生方式稱為多層派生多層派生,從繼承的角度看稱為多層繼承多層繼承。總84頁5 class 派生類名:繼承方式派生類名:繼承方式1 基類名基類名1, 繼承方式繼承方式2 基類名基類
3、名2, private: 派生類的私有數(shù)據(jù)和函數(shù)派生類的私有數(shù)據(jù)和函數(shù) public: 派生類的公有數(shù)據(jù)和函數(shù)派生類的公有數(shù)據(jù)和函數(shù) protected: 派生類的保護數(shù)據(jù)和函數(shù)派生類的保護數(shù)據(jù)和函數(shù);3、 派生類定義與實現(xiàn)派生類定義與實現(xiàn)派生類的定義派生類的定義“繼承方式1 基類名1, 繼承方式2 基類名2,”為基類名表基類名表, 表示當前定義的派生類的各個基類。如果基類名表中只有一個基類,表示定義的是單繼承;如果基類名表中有多個基類,表示定義的是多繼承。繼承方式指定了派生類成員以及類外對象對于從基類繼承來的成員的訪問權限在派生類的定義中,每一種繼承方式只限定緊跟其后的那個基類。如果不顯式給
4、出繼承方式,系統(tǒng)默認為私有繼承???4頁6class Clock private: int H,M,S; public: void SetTime(int H=0,int M=0,int S=0); void ShowTime(); Clock(int H=0,int M=0,int S=0); Clock();class AlarmClock: public Clockprivate: int AH,AM; /響鈴的時間響鈴的時間 bool OpenAlarm; /是否關閉鬧鐘是否關閉鬧鐘public: SetAlarm(int AH, int AM); /設置響鈴時設置響鈴時間間 Swit
5、chAlarm(bool Open=true); /打開打開/關閉關閉鬧鈴鬧鈴 ShowTime(); /顯示當前時間與鬧鈴時顯示當前時間與鬧鈴時間間 【例如】在普通的時鐘類Clock基礎上派生出鬧鐘類AlarmClock:類 名成 員 名AlarmClock:Clock:H, M, SSetTime()ShowTime()AH, AM, OpenAlarmSetAlarm()SwitchAlarm()ShowTime()AlarmClock()派生類派生類AlarmClock的成員構成圖的成員構成圖(表表) 總84頁7派生類的實現(xiàn)方式派生類的實現(xiàn)方式 (1) (1) 吸收基類成員吸收基類成員
6、 基類的全部成員被派生類繼承,作為派生類成員的一部分。如:Clock類中的數(shù)據(jù)成員H、M、S, 成員函數(shù)SetTime()、ShowTime()經(jīng)過派生,成為派生類AlarmClock的成員。 (2) (2) 改造基類成員改造基類成員 派生類根據(jù)實際情況對繼承自基類的某些成員進行限制和改造。對基類成員的訪問限制主要通過繼承方式來實現(xiàn);對基類成員的改造主要通過同名覆蓋同名覆蓋來實現(xiàn),即在派生類中定義一個與基類成員同名的新成員(如果是成員函數(shù),則函數(shù)參數(shù)表也必須相同,否則,C+會認為是函數(shù)重載)。派生類中的成員函數(shù)具有比基類中同名成員函數(shù)更小的作用域。 (3) (3) 添加新成員添加新成員 派生類
7、在繼承基類成員的基礎之上,根據(jù)派生類的實際需要,增加一些新的數(shù)據(jù)成員和函數(shù)成員,以描述某些新的屬性和行為???4頁8繼承的性質(zhì)繼承的性質(zhì) (1) (1) 繼承關系是可以傳遞的繼承關系是可以傳遞的 在派生過程中,一個基類可以同時派生出多個派生類,派生出來的新類也同樣可以作為基類再繼續(xù)派生新的派生類。這樣,就形成了一個相互關聯(lián)的類的家族,有時也稱作類族類族。 在類族中,直接派生出某類的基類稱為直接基類直接基類, 基類的基類甚至更高層的基類稱為間接基類間接基類,比如類A派生出類B,類B又派生出類C,則類B是類C的直接基類,類A是類B的直接基類,而類A稱為類C的間接基類。 (2) (2)繼承關系不允許
8、循環(huán)繼承關系不允許循環(huán) 在派生過程中,不允許類A派生出類B,類B又派生出類C,而類C又繼承自類A???4頁94、繼承與組合、繼承與組合 繼承描述的是一般類與特殊類的關系,類與類之間體現(xiàn)的是“is is a kind of”a kind of”,即如果在邏輯上A是B的一種(is a kind of),則允許A繼承B的功能和屬性。例如汽車(automobile)是交通工具(vehicle)的一種,小汽車(car)是汽車的一種。那么類automobile可以從類vehicle派生,類car可以從類automobile派生。 組合描述的是整體與部分的關系,類與類之間體現(xiàn)的是“is a is a par
9、t of”part of”,即如果在邏輯上A是B的一部分(is a part of),則允許A和其他數(shù)據(jù)成員組合為B。例如:發(fā)動機、車輪、電池、車門、方向盤、底盤都是小汽車的一部分,它們組合成汽車。而不能說發(fā)動機是汽車的一種。總84頁10l 繼承和組合既有區(qū)別,也有聯(lián)系,某些比較復雜的類,既需要使用繼承,也需要使用組合,二者一起使用。l在某些情況下,繼承與組合的實現(xiàn)還可以互換。在多繼承時,一個派生類有多個直接基類,派生類實際上是所有基類屬性和行為的組合。派生類是對基類的擴充,派生類成員一部分是從基類中來,因此派生類組合了基類。既然這樣,派生類也可以通過組合類實現(xiàn)。l 什么時候使用繼承,什么時候
10、使用組合,要根據(jù)問題類與類之間的具體關系,順其自然,權衡考慮。 總84頁11三種繼承方式下,基類成員在派生類中的訪問控制屬性總結如圖:三種繼承方式下,基類成員在派生類中的訪問控制屬性總結如圖: 基類屬性基類屬性繼承方式繼承方式 publicprotectedprivatepublicpublicprotected不可訪問不可訪問protectedprotectedprotected不可訪問不可訪問privateprivateprivate不可訪問不可訪問總84頁125、繼承的方式、繼承的方式 基類的公有成員在派生類中仍然為公有成員,可以由派生類對象和派生類成員函數(shù)直接訪問。 基類的私有成員在派
11、生類中,無論是派生類的成員還是派生類的對象都無法直接訪問。 保護成員在派生類中仍是保護成員,可以通過派生類的成員函數(shù)訪問,但不能由派生類的對象直接訪問。1) 公有繼承 公有方式繼承的特點:公有方式繼承的特點: F注意注意: : 對基類成員的訪問,一定要分清是通過派生類對象訪問還是通過派生類成員函數(shù)訪問。 總84頁13Example5-3.cppl#include lclass Baselpublic:lvoid setxy(int m,int n)lx=m;y=n; lvoid showxy(0lcoutx=xy=yendl;lprivate:lint x;lprotected:lint y;
12、lclass Derived:public Baselpublic:lvoid setxyz(int m,int n,int l)lsetxy(m,n);lz=l;lvoid showxyz()lcout“x=”xendl;/錯?lcout“y=”yendl;/對?lcoutz=zendl;lprivate:lint z;lmain()lDerived obj;lobj.setxyz(30,40,50);lobj.showxy();/對?錯?lobj.shoexyz();lreturn 0;總84頁14 【例【例8-1】公有繼承及其訪問 將點理解為半徑長度為0的圓,Point(點)類公有派生出
13、新的Circle(圓)類。圓類具備Point類的全部特征,同時自身也有自己的特點:圓有半徑。 123456789101112131415161718192021/Point.h#includeusing namespace std;class Pointprivate:int X,Y;public:Point(int X=0,int Y=0) this-X=X,this-Y=Y; void move(int OffX, int OffY) X+=OffX, Y+=OffY; void ShowXY() cout(X,Y)endl;總84頁1512345678910111213141516171
14、81920212223242526/* Circle.h * 從Point類派生出圓類(Circle) */#includepoint.hconst double PI=3.14159;class Circle :public Pointprivate:double radius; /半徑public: Circle(double R, int X, int Y):Point(X,Y)radius=R; double area() /求面積return PI*radius*radius; void ShowCircle() coutCentre of circle:; ShowXY(); co
15、utradius:radiusendl;類類 名名成成 員員 名名訪問訪問權限權限CirclePoint:X, Yprivate不可不可訪問訪問move()publicpublicShowXY()publicpublicradiusprivatearea()publicShowCircle()publicCircle()public總84頁163132333435363738394041424344/* p8_1.cpp * Circle 類的使用 */#include Circle.husing namespace std;void main() Circle Cir1(100,200,10
16、);Cir1.ShowCircle(); coutarea is:Cir1.area()endl;Cir1.move(10,20); Cir1.ShowXY();Centre of circle:(100,200) radius:10area is:31415.9(110,30) 總84頁17l【例【例6-2】 公有繼承舉例。l/examplech602.cpplclass Point /基類Pointllpublic: l void InitPoint(float PointA_x=0, float PointA_y=0)/公有函數(shù)成員llP1_x=PointA_x;lP1_y=PointA
17、_y;llvoid Move(float New_x, float New_y) /公有函數(shù)成員l lP1_x+=New_x;lP1_y+=New_y;llfloat GetPointx()l lreturn P1_x;llfloat GetPointy()l lreturn P1_y;llprivate: /私有數(shù)據(jù)成員lfloat P1_x,P1_y;l;總84頁18lclass Circle: public Point llpublic: /新增公有函數(shù)成員lvoid InitCircle(float P1_x, float P1_y, float Radius)llInitPoint(
18、P1_x,P1_y); /調(diào)用基類公有成員函數(shù)lR=Radius; l lfloat GetRadius()l lreturn R;llprotected: lfloat R; /新增保護數(shù)據(jù)成員l;總84頁19lclass Rectangle: public Pointllpublic: /新增公有函數(shù)成員lvoid InitRect(float P1_x, float P1_y, float Rect_H, float Rect_W)llInitPoint(P1_x,P1_y); /調(diào)用基類公有成員函數(shù)lHigh=Rect_H;lWide=Rect_W;l lfloat GetHigh()
19、l lreturn High; llfloat GetWide()l lreturn Wide; llprotected: /新增數(shù)據(jù)成員lfloat High;lfloat Wide;l;總84頁20l#include Point.hl#includelvoid main()llCircle C1; /定義Circle類的對象lC1.InitCircle(10,10,28); lC1.Move(10,10); /移動到新位置lcoutThe Data of Circle(P1_x,P1_y,R):endl;lcoutC1.GetPointx(),C1.GetPointy(),lC1.GetR
20、adius(),endl; /輸出參數(shù)lRectangle Rect1; /定義Rectangle類的對象lRect1.InitRect(5,5,20,30); lRect1.Move(10,10); /移動到新位置lcoutThe Data of Rect(P1_x,P1_y,High,Wide):endl;lcoutRect1.GetPointx(), /輸出參數(shù)lRect1.GetPointy(),lRect1.GetHigh(),Rect1.GetWide()endl;l總84頁21類Point:Public: initPoint(); move(); GetPointx(); Get
21、Pointy()Private: float p1_x,p1_y 類Circle:Public: initCircle(); GetRadius();Protected: R; 類Rectangle:Public: initRect(); GetHigh(); GetWide()Protected: High; Wide; Public繼承 Public繼承 總84頁22lExercise 1: 寫一個圓類,再寫一個圓球類,圓球類從圓類公有繼承(要求不要寫構造和析構) 總84頁232) 私有繼承 基類的公有成員和保護成員被繼承后作為派生類的私有成員,即基類的公有成員和保護成員被派生類吸收后,派
22、生類的其他成員函數(shù)可以直接訪問它們,但是在類外部,不能通過派生類的對象訪問它們。 基類的私有成員在派生類中不能被直接訪問。無論是派生類的成員還是通過派生類的對象,都無法訪問從基類繼承來的私有成員。 經(jīng)過私有繼承之后,所有基類的成員都成為了派生類的私有成員或不可訪問的成員,如果進一步派生的,基類的全部成員將無法在新的派生類中被訪問。 因此,私有繼承之后,基類的成員再也無法在以后的派生類中發(fā)揮作用,實際是相當于中止了基類的繼續(xù)派生私有方式繼承的特點:私有方式繼承的特點: 總84頁24私有繼承方式下,基類成員在派生類中的訪問控制屬性總結如圖:私有繼承方式下,基類成員在派生類中的訪問控制屬性總結如圖:
23、 基類屬性基類屬性繼承方式繼承方式 publicprotectedprivateprivateprivateprivate不可訪問不可訪問總84頁25 【例【例8-2】私有繼承派生類的實現(xiàn)及其訪問/ Circle2.h#includepoint.hconst double PI=3.14159;class Circle :private Pointprivate:double radius; /半徑public:double area(); /求面積void ShowCircle();void move(int OffX,int OffY)point:move(OffX,OffY);類類 名名
24、成成 員員 名名訪問權限訪問權限CirclePoint:X,Yprivate不可訪問不可訪問move()publicprivateShowXY()publicprivateradiusprivatearea()publicShowCircle()publicCircle()public總84頁26運行結果Centre of circle:(100,200) radius:10area is:31415.9(110,30) #include Circle2.husing namespace std;void main() Circle Cir1(100,200,10);Cir1.ShowCirc
25、le();coutarea is:Cir1.area()endl;Cir1.move(10,20); /同名覆蓋 / Cir1.ShowXY(); /錯誤,ShowXY()繼承為私有成員函數(shù)對比兩個示例程序,可以看出:由于是私有繼承,基類中的所有成員在派生類中都成為私有成員,因此派生類對象不能直接訪問任何一個基類的成員。類Circle的對象Cir1調(diào)用的都是派生類自身的公有成員。本例僅僅對派生類的實現(xiàn)作了適當?shù)男薷?,基類和主程序部分沒有做任何改動,程序運行的結果同前例。由此可見面向?qū)ο蟪绦蛟O計封裝性的優(yōu)越性,這正是面向?qū)ο蟪绦蛟O計可重用與可擴充性的一個實際體現(xiàn)???4頁27Example5-1
26、.cppl#includelclass Baselpublic:lvoid setx(int n)x=n;lvoid showx()coutxendl;lprivate:lint x;l;lclass Derived:private Baselpublic:lvoid setxy(int n,int m)lsetx(n);ly=m;lvoid showxy()lcoutx;/錯,為什么?l coutyendl; lprivate:lint y;l;lmain()lDerived obj;lobj.setx(10);/錯。?lobj.showx();/錯,?lobj.setxy(20,30);l
27、obj.shoexy();lreturn 0;總84頁283) 保護繼承 基類的公有成員和保護成員被繼承后作為派生類的保護成員。 基類的私有成員在派生類中不能被直接訪問。 修改Circle2.h,將派生類的繼承方式改為保護繼承,其它部分不變:保護繼承的特點:保護繼承的特點: /circle3.h#include “piont.h”class Circle :protected point/類成員定義類類 名名成成 員員 名名訪問權限訪問權限CirclePoint:X,Yprivate不可訪問不可訪問move()publicprotectedShowXY()publicprotectedradi
28、usprivatearea()publicShowCircle()publicCircle()public總84頁29運行結果Centre of circle:(100,200) radius:10area is:31415.9(110,30) #include Circle3.husing namespace std;void main() Circle Cir1(100,200,10);Cir1.ShowCircle();coutarea :Cir1.area() endl;Cir1.move(10,20); /同名覆蓋 / Cir1.ShowXY(); /錯誤,ShowXY()繼承為保護
29、成員函數(shù) private、protected兩種繼承方式下,基類所有成員在派生類中的訪問屬性都是完全相同的。即在派生類中可以訪問基類的公有、保護成員不可訪問基類的私有成員。 總84頁30如果將派生類作為新的基類繼續(xù)派生時,private、 protected兩種繼承方式區(qū)別就出現(xiàn)了。假設類B以私有方式繼承自類A,則無論B類以什么方式派生出類C,類C的成員和對象都不能訪問間接從A類中繼承來的成員。但如果類B是以保護方式繼承自類A,那么類A中的公有和保護成員在類B中都是保護成員。類B再派生出類C后,如果是公有派生或保護派生,則類A中的公有和保護成員被類C間接繼承后,類C的成員函數(shù)可以訪問間接從類A
30、中繼承來的成員。即類A的成員可以沿繼承樹繼續(xù)向下傳播。總84頁31 【例【例8-2 】保護繼承與保護成員的訪問 修改例8-1,除將基類Point的數(shù)據(jù)成員X和Y的訪問屬性改為protected外,又增加了一個派生類:Cylinder(圓柱體)類。Cylinder類保護繼承自類circle。程序?qū)崿F(xiàn)如下: 123456789101112131415161718192021/Point2.h#includeusing namespace std;class Pointprotected:int X,Y;public:Point(int X=0,int Y=0) this-X=X,this-Y=Y;
31、 void move(int OffX, int OffY) X+=OffX, Y+=OffY; void ShowXY() cout(X,Y)endl;總84頁321234567891011121314151617181920212223242526272829303132/* p8_2.cpp * 從circle類派生出圓柱類(Cylinder) */#includepoint2.hconst double PI=3.14159;class Circle :protected Pointprotected:double radius; /半徑public: Circle(double R,
32、 int X, int Y):Point(X,Y)radius=R; double area() /求面積return PI*radius*radius; void ShowCircle() coutCentre of circle:; ShowXY(); coutradius:radiusendl;class Cylinder: protected Circleprivate:double height;public: Cylinder(int X, int Y, double R, double H):Circle(R,X,Y)3334353637383940414243444546474
33、84950515253545556 height=H; double area() return 2*Circle:area()+2*PI*radius*height; double volume() return Circle:area()*height;void ShowCylinder() ShowCircle(); coutheight of cylinder:heightendl;void main() Cylinder CY(100,200,10,50);CY.ShowCylinder();couttotal area:CY.area()endl;coutvolume:CY.vol
34、ume();運行結果Centre of circle:(100,200) radius:10height of cylinder:50total area :3769.11volume : 15707.9 總84頁331234567891011121314151617181920212223242526272829303132/* p8_2.cpp * 從circle類派生出圓柱類(Cylinder) */#includepoint2.hconst double PI=3.14159;class Circle :protected Pointprotected:double radius; /
35、半徑public: Circle(double R, int X, int Y):Point(X,Y)radius=R; double area() /求面積return PI*radius*radius; void ShowCircle() coutCentre of circle:; ShowXY(); coutradius:radiusendl;class Cylinder: protected Circleprivate:double height;public: Cylinder(int X, int Y, double R, double H):Circle(R,X,Y)33343
36、5363738394041424344454647484950515253545556 height=H; double area() return 2*Circle:area()+2*PI*radius*height; double volume() return Circle:area()*height;void ShowCylinder() ShowCircle(); coutheight of cylinder:heightendl;void main() Cylinder CY(100,200,10,50);CY.ShowCylinder();couttotal area:CY.ar
37、ea()endl;coutvolume:CY.volume(); Circle保護繼承自類Point,因此類Circle為子類,類Point為父類,對于該子類來講,保護成員與公有成員具有相同的訪問特性。所以派生類的成員函數(shù)ShowCircle()可以訪問基類從基類繼承而來的保護成員,當然它也可以調(diào)用從基類繼承來的公有成員函數(shù)ShowXY()。 類Circle沿類的繼承樹繼續(xù)派生出類Cylinder,繼承方式依然為保護繼承,因此,在類cylinder中,它間接從類Point中繼承了四個保護成員:數(shù)據(jù)成員X、Y,以及成員函數(shù)move()、ShowXY();同時它也直接從其父類Circle中繼承了3
38、個類成員:數(shù)據(jù)成員radius, 成員函數(shù)ShowCircle()、area(),它們都以保護成員的身份出現(xiàn)在類Cylinder中。因此,在類Cylinder的成員函數(shù)ShowCylinder()中,不僅可以訪問從父類Circle中直接繼承來的成員函數(shù)ShowCircle(),而且可以訪問沿繼承樹從基類Point中間接繼承來的數(shù)據(jù)成員X和Y。 當通過類Cylinder的對象CY調(diào)用成員函數(shù)area()時,由于對象CY擁有兩個同名成員函數(shù)area(),一個是從其父類Circle繼承來的,一個是類Cylinder自己新增的,二者函數(shù)體實現(xiàn)完全不同。類Circle的成員函數(shù)area()和派生類Cyl
39、inder新增的成員函數(shù)area()都具有類作用域,二者的作用范圍不同,是相互包含的兩個層,派生類在內(nèi)層。由于,派生類Cylinder聲明了一個和其父類circle成員同名的新成員area(),派生的新成員函數(shù)就覆蓋了外層父類的同名成員函數(shù),直接使用成員名只能訪問到派生類自己新增的同名成員函數(shù)。C+利用同名覆蓋原則,自動選擇調(diào)用類Cylinder新增的成員函數(shù)area(),輸出圓柱體的總的表面積,這再一次體現(xiàn)了繼承機制所產(chǎn)生的程序重用性和可擴充性???4頁34l【例【例6-4】 保護繼承。將例6-2中的Circle類的繼承方式改為保護繼承,這時Circle類還可以繼續(xù)派生出新類。未注明的“”表
40、示與例6-2對應部分代碼相同。l/examplech604.cpplclass Point /基類Point類定義ll /l;lclass Circle: protected Pointll/ 例6-3對應部分相同1.;總84頁35lclass DCircle: protected Circle /定義Circle的派生類Dcircle(園環(huán))llpublic: lvoid InitDCircle(float P1_x, float P1_y,float Radius_i,float Radius_o)lInitPoint(P1_x,P1_y);l R_inside=Radius_i;l R_
41、outside=Radius_o;l lvoid Move(float New_x, float New_y)lPoint:Move(New_x,New_y);lfloat GetPointx()lreturn Point:GetPointx();llfloat GetPointy() lreturn Point:GetPointy();llfloat GetRadius_i()lreturn R_inside;llfloat GetRadius_o()lreturn R_outside;llprivate:l float R_inside,R_outside;l;總84頁36lclass R
42、ectangle: public Point /派生類定義l /l;l#includelvoid main()ll Circle C1; /定義對象C1l C1.InitCircle(10,10,28); lC1.Move(10,10); /移動到新位置l coutThe Data of Circle(P1_x,P1_y,R):endl;lcoutC1.GetPointx(),C1.GetPointy(),C1.GetRadius(),endl; l DCircle DC1; /定義圓環(huán)對象DC1l DC1.InitDCircle(10,10,28,38); l DC1.Move(10,10)
43、; /圓環(huán)移動到新位置lcoutThe Data of DCircle(CircleCenter_x,CircleCenter_y ,R_inside,R_outside):endl;l coutDC1.GetPointx(),C1.GetPointy(), DC1.GetRadius_i(),l DC1.GetRadius_o(),endl;l Rectangle Rect1; l Rect1.InitRect(5,5,20,30); l Rect1.Move(10,10); l coutThe Data of Rect(P1_x,P1_y,High,Wide):endl;l coutRec
44、t1.GetPointx(), Rect1.GetPointy(),l Rect1.GetHigh(),Rect1.GetWide()endl;l 總84頁37類Point:Public: initPoint(); move(); GetPointx(); GetPointy()Private: float p1_x,p1_y 類Circle:Public: initCircle(); GetRadius(); move(); GetPointx(); GetPointy()Protected: R; 類DCircle:Public: initDCircle(); Move(); GetPoi
45、ntx(); GetPointy() GetRadius_o() GetRadius_o()Protected: R_inside; R_outside; protected繼承 protected繼承 public繼承 類Rectangle:Public: initRect(); GetHigh(); GetWide()Protected: High; Wide; 總84頁38三種繼承方式下,基類成員在派生類中的訪問控制屬性總結如圖:三種繼承方式下,基類成員在派生類中的訪問控制屬性總結如圖: 基類屬性基類屬性繼承方式繼承方式 publicprotectedprivatepublicpubli
46、cprotected不可訪問不可訪問protectedprotectedprotected不可訪問不可訪問privateprivateprivate不可訪問不可訪問總84頁39Exercise 2PointTriangleRectanglePointTriangleRectangleCircleCircleCylinder總84頁406、派生類的構造與析構、派生類的構造與析構 1.派生類構造函數(shù)的定義 派生類名派生類名(參數(shù)總表參數(shù)總表): 基類名基類名1(參數(shù)表參數(shù)表1),.,基類名基類名m (參數(shù)表參數(shù)表m),成員對象名成員對象名1(成員對象參數(shù)表成員對象參數(shù)表1),.,成員對象名成員對象
47、名n(成員對象參數(shù)表成員對象參數(shù)表n) 派生類新增成員的初始化;派生類新增成員的初始化; 基類名1(參數(shù)表1),.,基類名m (參數(shù)表m)稱為基類成員的初始化表基類成員的初始化表。 成員對象名1(成員對象參數(shù)表1),.,成員對象名n(成員對象參數(shù)表n) 為成員對象成員對象的初始化表的初始化表。總84頁41基類成員的初始化表與成員對象的初始化表構成派生類構造函數(shù)的初初始化表始化表。在派生類構造函數(shù)的參數(shù)總表參數(shù)總表中,需要給出基類數(shù)據(jù)成員的初值、成員對象數(shù)據(jù)成員的初值、新增一般數(shù)據(jù)成員的初值。在參數(shù)總表之后,列出需要使用參數(shù)進行初始化的基類名、成員對象名及各自的參數(shù)表,各項之間使用逗號分隔。基類
48、名、對象名之間的次序無關緊要,它們各自出現(xiàn)的順序可以是任意的。在生成派生類對象時,程序首先會使用這里列出的參數(shù),調(diào)用基類和成員對象的構造函數(shù)???4頁42 如果基類定義了帶有形參表的構造函數(shù)時,派生類就應當定義構造函數(shù),提供一個將參數(shù)傳遞給基類構造函數(shù)的途徑,保證在基類進行初始化時能夠獲得必要的數(shù)據(jù)。 如果基類沒有定義構造函數(shù),派生類也可以不定義構造函數(shù),全部采用默認的構造函數(shù),這時新增成員的初始化工作可以用其他公有成員函數(shù)來完成???4頁43 調(diào)用基類構造函數(shù); 調(diào)用內(nèi)嵌成員對象的構造函數(shù),調(diào)用順序按照它們在類中定義的順序 。 派生類自己的構造函數(shù)。 2 單繼承的構造與析構單繼承的構造與析構
49、單繼承時,派生類構造函數(shù)調(diào)用的一般次序如下: 當派生類對象析構時,各析構函數(shù)的調(diào)用順序正好相反。首先調(diào)用派生類析構函數(shù)(清理派生類新增成員);然后調(diào)用派生類成員對象析構函數(shù)(清理派生類新增的成員對象);最后調(diào)用基類析構函數(shù)(清理從基類繼承來的基類子對象)。 總84頁44 【例【例8-3】單繼承的構造與析構。 為了說明單繼承的構造,由Point類派生出Circle類,再由兩個同心Circle類對象與高度height構成空管Tube類。構成空管的兩個同心圓的外圓從Circle類繼承,內(nèi)圓組合Circle類對象InCircle。Tube類的層次結構圖如圖: 總84頁45123456789101112
50、131415161718192021222324252627282930313233343536/* p8_3.cpp * 多層繼承的構造函數(shù)與析構函數(shù) */#includeusing namespace std;class Pointprivate:int X,Y;public:Point(int X=0,int Y=0) this-X=X,this-Y=Y coutpoint(X,Y) constructing.endl;Point()coutpoint(X,Y) destructing.endl;class Circle :protected Pointprotected:double
51、radius; /半徑public:Circle(double R=0,int X=0, int Y=0):Point(X,Y)radius=R;coutcircle constructing, radius:Rendl;Circle() coutcircle destructing, radius:radiusendl;373839404142434445464748495051525354555657class tube: protected Circleprivate:double height; Circle InCircle;public:tube(double H,double R
52、1, double R2=0, int X=0, int Y=0 ):InCircle(R2,X,Y),Circle(R1,X,Y) height=H; couttube constructing, height:Hendl; tube() couttube destructing, height:heightendl;void main() tube TU(100,20,5);運行結果point(0,0) constructing.circle constructing, radius:20point(0,0) constructing.circle constructing, radius
53、:5tube constructing, height:100tube destructing, height:100circle destructing, radius:5point(0,0) destructing.circle destructing, radius:20point(0,0) destructing. 定義了一個派生類Tube的對象TU,首先試圖調(diào)用類Tube的構造函數(shù); 類Tube是派生類,由基類Circle派生,于是試圖調(diào)用Circle類的構造函數(shù); 類Circle的基類是Point, 沿繼承樹上溯至頂層基類Point,調(diào)用Point類的構造函數(shù); Tube同時又是一
54、個組合類,由對象InCircle組合而成,于是,再從頂層基類Point開始,依次調(diào)用調(diào)用Point類的構造函數(shù)、Circle的構造函數(shù)。 當退出主函數(shù)之前,程序沿繼承樹自底向上依次調(diào)用各類的析構函數(shù),其順序與構造函數(shù)順序正好相反???4頁46練習:分析以下程序的執(zhí)行結果練習:分析以下程序的執(zhí)行結果 l#include lclass base l lpublic: lbase()coutconstructing base classendl; lbase()coutdestructing base classendl; l; lclass subs:public base l lpublic:
55、lsubs()coutconstructing sub classendl; lsubs()coutdestructing sub classendl; l; lvoid main() l lsubs s; l constructing base class constructing sub class destructing sub class destrcuting base class總84頁47constrcuting base class n=1 constructing base class n=3 constructing sub class m=2 destructing su
56、b class destructing base class destructing base class l#include lclass base l lint n; lpublic: lbase(int a) l lcoutconstructing base classendl; ln=a; lcoutn=nendl; l lbase()coutdestructing base classendl; l; lclass subs:public base l lbase bobj; lint m; lpublic: lsubs(int a,int b,int c):base(a),bobj
57、(c) l lcoutconstructing sub cassendl; lm=b; lcoutm=mendl; l lsubs()coutdestructing sub classendl; l; lvoid main() l lsubs s(1,2,3); l 注意:當派生類中含有對象成員時,構造函數(shù)的調(diào)用順序如下: 1)基類的構造函數(shù) 2)對象成員的構造函數(shù) 3)派生類的構造函數(shù) 析構函數(shù)的調(diào)用順序與之相反 總84頁48 在C+中,類型兼容主要指以下三種情況: 派生類對象可以賦值給基類對象。 派生類對象可以初始化基類的引用。 派生類對象的地址可以賦給指向基類的指針。7、類型兼容、類型兼
58、容 類型兼容類型兼容是指在公有派生的情況下,一個派生類對象可以作為基類的對象來使用。類型兼容又稱為類型賦值兼容或類型適應。 【例【例8-4】演示類的兼容性。 前面我們定義了類Point,它公有派生出類Circle,后者進一步公有派生出類Cylinder。我們可以通過這個單繼承的例子來驗證類型兼容規(guī)則???4頁49運行結果(1,1)(20,20)(300,300)(300,300)(20,20) 8.4 8.4 類型兼容類型兼容1234567891011121314151617181920212223242526272829303132333435363738/* p8_4.cpp * 從cir
59、cle類公有派生出圓柱類Cylinder * 演示類的兼容性 */#includeCircle.hclass Cylinder: public Circleprivate:double height;public: Cylinder(int X, int Y, double R, double H):Circle(X,Y,R) height=H; void ShowCylinder() ShowCircle(); coutheight of cylinder:heightShowXY(); Pp=&Cir; /將派生類對象地址賦給指向基類的指針 Pp-ShowXY(); Pp=&
60、;CY; /將派生類對象地址賦給指向基類的指針 Pp-ShowXY(); Circle & RC=CY; /Circle類引用引用了派生類Cylinder對象 RC.ShowXY(); P=Cir; /Circle類對象賦值給基類Point類對象 P.ShowXY();定義了Point類型的指針Pp 指向了Point類對象 指向了Circle類對象 指向了Cylinder類對象 Pp調(diào)用了Point 類的成員函數(shù)ShowXY(), 顯示了Point類對象的中心坐標值。 調(diào)用了Point 類的成員函數(shù)ShowXY(), 顯示了Circle類對象的中心坐標值。 調(diào)用了Point 類的成員函數(shù)ShowXY(), 顯示了C
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026年甘肅省隴南地區(qū)單招職業(yè)適應性測試模擬測試卷附答案
- 2026年湖南省邵陽市單招職業(yè)適應性考試題庫附答案
- 2026年民辦四川天一學院單招職業(yè)技能考試題庫及答案1套
- 2026年廣東金融學院單招綜合素質(zhì)考試題庫及答案1套
- 2026年電工電子期末測試題及答案(奪冠)
- 2025寧波市甬北糧食收儲有限公司公開招聘工作人員2人筆試模擬試題及答案解析
- 吉水縣旅游開發(fā)投資有限公司2026年面向社會公開招聘2名場館營業(yè)員筆試模擬試題及答案解析
- 2026云南紅河老兵聯(lián)綜合保障服務有限公司保安員招聘1人筆試模擬試題及答案解析
- 2026銅川市新區(qū)文家中學教師招聘筆試備考試題及答案解析
- 2025年七臺河桃山區(qū)招聘社區(qū)工作者27人考試參考題庫附答案
- 建筑設計防火規(guī)范-實施指南
- 2025國開《中國古代文學(下)》形考任務1234答案
- 肺部感染中醫(yī)護理
- 租地合同協(xié)議書合同
- 《肺炎的CT表現(xiàn)》課件
- 糧食倉儲設施建設維修資金申請報告
- 腦器質(zhì)性精神障礙護理查房
- 中考英語聽力命題研究與解題策略省公開課金獎全國賽課一等獎微課獲獎課件
- 物聯(lián)網(wǎng)智能家居設備智能控制手冊
- 2023-2024學年湖北省武漢市東西湖區(qū)五年級(上)期末數(shù)學試卷(含答案)
- 全國班主任比賽一等獎《班主任經(jīng)驗交流》課件
評論
0/150
提交評論