《c++程序設(shè)計(jì)》課件-第4章 繼承與組合_第1頁(yè)
《c++程序設(shè)計(jì)》課件-第4章 繼承與組合_第2頁(yè)
《c++程序設(shè)計(jì)》課件-第4章 繼承與組合_第3頁(yè)
《c++程序設(shè)計(jì)》課件-第4章 繼承與組合_第4頁(yè)
《c++程序設(shè)計(jì)》課件-第4章 繼承與組合_第5頁(yè)
已閱讀5頁(yè),還剩160頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

第4章繼承與組合1234繼承與派生的概念第4章繼承與組合本章學(xué)習(xí)要點(diǎn)派生類的構(gòu)成派生類的聲明方式派生類中基類成員的訪問屬性25678派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)第4章繼承與組合本章學(xué)習(xí)要點(diǎn)基類與派生類對(duì)象的關(guān)系多重繼承組合——對(duì)象組成對(duì)象3本章學(xué)習(xí)目標(biāo)1.理解繼承和派生的概念;2.掌握派生類的聲明方式,派生類的構(gòu)成;3.掌握三種不同繼承方式對(duì)基類成員、派生類成員訪問權(quán)限的影響;3.掌握派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)的執(zhí)行時(shí)機(jī);4.掌握多重繼承的聲明方法;多重繼承派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)的定義及執(zhí)行;5.理解虛基類的概念,掌握其作用和聲明方法;6.理解組合的概念,掌握繼承與組合在軟件開發(fā)中的意義。第4章繼承與組合4現(xiàn)實(shí)世界中的例子幾何形狀矩形圓汽車工具車轎車面包車旅行車卡車交通工具小汽車飛機(jī)船5現(xiàn)實(shí)世界中的例子猴子鳥貓科動(dòng)物獅子獵豹虎銷售經(jīng)理經(jīng)理工人銷售人員職員6面向?qū)ο蠹夹g(shù)強(qiáng)調(diào)軟件的可重用性(softwarereusability)。C++語言提供了類的繼承機(jī)制,解決了軟件重用問題。第4章繼承與組合通過繼承機(jī)制,可以方便地利用一個(gè)已有的類建立新類,重用已有軟件中的部分甚至很大的部分。微軟基礎(chǔ)類MFC,就是通過類的繼承來體現(xiàn)類的可重用性和可擴(kuò)充性7在C++中,所謂“繼承”就是在一個(gè)或多個(gè)已存在的類的基礎(chǔ)上建立一個(gè)新的類。已存在的類稱為“基類”、“父類”或“一般類”。新建立的類稱為“派生類”、“子類”或“特殊類”。

4.1繼承與派生的概念第4章繼承與組合8一個(gè)新類從已有的類那里獲得其已有特性,這種現(xiàn)象稱為類的繼承。通過繼承,一個(gè)新建子類從已有的父類那里獲得父類的特性。從另一角度說,從已有的父類產(chǎn)生一個(gè)新的子類,稱為類的派生。類的繼承是用已有的類來建立專用類的編程技術(shù)。4.1繼承與派生的概念第4章繼承與組合9派生類繼承了基類的所有數(shù)據(jù)成員和成員函數(shù)(不包括基類的構(gòu)造函數(shù)和析構(gòu)函數(shù)),并可以增加自己的新成員,同時(shí)也可以調(diào)整來自基類的數(shù)據(jù)成員和成員函數(shù)。基類和派生類是相對(duì)而言的。一個(gè)基類可以派生出多個(gè)派生類,每一個(gè)派生類又可以作為基類再派生出新的派生類。一代一代地派生下去,就形成了類的繼承層次結(jié)構(gòu)4.1繼承與派生的概念第4章繼承與組合10圖4-1單繼承中學(xué)生學(xué)生初中生高中生??粕究粕芯可T士生博士生大學(xué)生小學(xué)生留學(xué)生一個(gè)派生類只從一個(gè)基類派生,這稱為單繼承(singleinheritance),這種繼承關(guān)系所形成的層次是一個(gè)樹形結(jié)構(gòu),可以用圖4-1表示。第4章繼承與組合11圖4-2多繼承銷售經(jīng)理經(jīng)理工人銷售人員職員一個(gè)派生類不僅可以從一個(gè)基類派生,也可以從多個(gè)基類派生。一個(gè)派生類有兩個(gè)或多個(gè)基類的稱為多重繼承(multipleinheritance),這種繼承關(guān)系所形成的結(jié)構(gòu)如圖4-2所示。第4章繼承與組合基類和派生類的關(guān)系,可以表述為:

派生類是基類的具體化,而基類是派生類的抽象。4.1繼承與派生的概念第4章繼承與組合13單繼承派生類的聲明格式如下:class

派生類名:[繼承方式]基類名{

派生類新增加的成員};4.2派生類的聲明方式第4章繼承與組合14class

Circle

//聲明基類{public:

//基類公用成員

voidSetRadius(intr){radius=r;}intGetRadius(){returnradius;}

voidShowRadius(){cout<<"BaseclassCircle:radius="<<radius<<endl;}private://基類私有成員

intradius;};15class

Cylinder:

publicCircle{public:voidSetHeight(inth){height=h;}intGetHeight(){returnheight;}voidShowHeight(){cout<<"Derivedclass

Cylinder:height="<<height<<endl;}private:intheight;};第4章繼承與組合圖4-3基類Circle和派生類Cylinder的成員示意圖16派生類中的成員包從基類繼承過來的成員括和自己新增加的成員兩大部分,從基類繼承過來的成員體現(xiàn)了派生類從基類繼承而獲得的共性,而新增加的成員體現(xiàn)了派生類的個(gè)性,體現(xiàn)了派生類與基類的不同,體現(xiàn)了不同派生類的區(qū)別。4.3派生類的構(gòu)成第4章繼承與組合17184.3派生類的構(gòu)成從基類接收成員。派生類把基類全部的成員(不包括構(gòu)造函數(shù)和析構(gòu)函數(shù))接收過來,也就是說沒有選擇的,不能選擇接收其中一部分成員,而舍棄另一部分成員。調(diào)整從基類接收的成員。在聲明派生類時(shí)增加的成員。接收基類成員是程序員不能選擇的,但是程序人員可以對(duì)這些成員作某些調(diào)整。改變?cè)L問屬性;用同名新成員覆蓋基類的同名成員;它體現(xiàn)了派生類對(duì)基類的擴(kuò)展。定義派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)。19派生類成員的訪問屬性在討論訪問屬性時(shí),需要考慮以下幾種情況:基類的成員函數(shù)訪問基類成員;派生類的成員函數(shù)訪問派生類自己增加的成員;派生類的成員函數(shù)訪問基類成員;在派生類外訪問派生類的成員;在派生類外訪問基類的成員;√√派生類中基類成員的訪問屬性不僅與在聲明基類時(shí)所聲明的訪問屬性有關(guān),而且與在聲明派生類時(shí)所指定的對(duì)基類的繼承方式有關(guān),這兩個(gè)因素共同決定基類成員在派生類中的訪問屬性。4.4派生類中基類成員的訪問屬性第4章繼承與組合20派生類對(duì)基類的繼承方式有public,private和protected3種。不同的繼承方式?jīng)Q定了基類成員在派生類中的訪問屬性。(1)公用繼承(publicinheritance)基類的公用成員和保護(hù)成員在派生類中保持原有訪問屬性,其私有成員仍為基類私有。4.4派生類中基類成員的訪問屬性第4章繼承與組合21(2)私有繼承(privateinheritance)基類的公用成員和保護(hù)成員在派生類中成了私有成員。其私有成員仍為基類私有。4.4派生類中基類成員的訪問屬性第4章繼承與組合22(3)受保護(hù)的繼承(protectedinheritance)基類的公用成員和保護(hù)成員在派生類中成了保護(hù)成員,其私有成員仍為基類私有。

保護(hù)成員的意思是:不能被外界訪問,但可以被派生類的成員訪問。4.4派生類中基類成員的訪問屬性第4章繼承與組合23在聲明一個(gè)派生類時(shí)將基類的繼承方式指定為public的,稱為公用繼承。用公用繼承方式建立的派生類稱為公用派生類(publicderivedclass),其基類稱為公用基類(publicbaseclass)。4.4.1公用繼承第4章繼承與組合244.4.1公用繼承第4章繼承與組合表4-1公用基類成員在派生類中的訪問屬性公用基類的成員在公用派生類中的訪問屬性私有成員不可訪問公用成員公用保護(hù)成員保護(hù)25第4章繼承與組合【例4-1】公用繼承的例子。

#include<iostream>usingnamespacestd;class

Circle

//聲明基類{public:

//基類公用成員

voidSetRadius(intr){radius=r;}intGetRadius(){returnradius;}

voidShowRadius(){

cout<<"BaseclassCircle:radius="<<radius<<endl;}private://基類私有成員

intradius;};26class

Cylinder:

publicCircle{public:voidSetHeight(inth){height=h;}intGetHeight(){returnheight;}voidShowHeight(){cout<<"Derivedclass

Cylinder:height="<<height<<endl;}voidSet(intr,inth){//radius=r;SetRadius(r);height=h;}voidShow(){//cout<<"radius="<<radius<<endl;

cout<<"radius="<<GetRadius()<<endl;

//ShowRadius();

cout<<"height="<<height<<endl;

}private:intheight;};27

intmain()

{Cylinderobj;

obj.SetRadius

(10);

obj.showRadius();

obj.SetHeight(20);

obj.ShowHeight();

obj.Set(30,40);

obj.Show();

return0;

}第4章繼承與組合程序運(yùn)行結(jié)果如下:BaseclassCircle:radius=10Derivedclass

Cylinder:height=20radius=30height=402829公有繼承舉例classPoint //基類Point類的聲明{public: //公有函數(shù)成員

voidInitP(floatxx=0,floatyy=0){X=xx;Y=yy;} voidMove(floatxOff,floatyOff){X+=xOff;Y+=yOff;} floatGetX(){returnX;} floatGetY(){returnY;}private: //私有數(shù)據(jù)成員

floatX,Y;};30classRectangle:publicPoint//派生類聲明{public: //新增公有函數(shù)成員

voidInitR(floatx,floaty,floatw,floath) {InitP(x,y);W=w;H=h;}//調(diào)用基類公有成員函數(shù)

floatGetH(){returnH;} floatGetW(){returnW;}private: //新增私有數(shù)據(jù)成員

floatW,H;};公有繼承舉例31intmain(){Rectanglerect; rect.InitR(2,3,20,10);

//通過派生類對(duì)象訪問基類公有成員

rect.Move(3,2); cout<<rect.GetX()<<',' <<rect.GetY()<<',' <<rect.GetH()<<',' <<rect.GetW()<<endl; return0;}公有繼承舉例復(fù)習(xí)有類Point如下:classPoint //基類Point類的聲明{public: //公有函數(shù)成員

voidInitP(floatxx=0,floatyy=0){X=xx;Y=yy;} voidMove(floatxOff,floatyOff){X+=xOff;Y+=yOff;} floatGetX(){returnX;} floatGetY(){returnY;}private: //私有數(shù)據(jù)成員

floatX,Y;};以Point為父類,定義一個(gè)子類Circle類,繼承方式為公有繼承,Circle類中新增私有數(shù)據(jù)成員r和公有成員函數(shù)GetR(),要求在main()函數(shù)中,子類對(duì)象能夠使用InitP(),Move(),GetX(),GetY()和GetR()。在聲明一個(gè)派生類時(shí)將基類的繼承方式指定為private的,稱為私有繼承。用私有繼承方式建立的派生類稱為私有派生類(privatederivedclass),其基類稱為私有基類(privatebaseclass)。4.4.2私有繼承第4章繼承與組合334.4.2私有繼承第4章繼承與組合表4-2私有基類成員在派生類中的訪問屬性私有基類的成員在私有派生類中的訪問屬性私有成員不可訪問公用成員私有保護(hù)成員私有34第4章繼承與組合【例4-2】將【例4-1】中的公用繼承方式改為用私有繼承方式。classCircle//聲明基類Circle——圓類{public://Circle類公用成員函數(shù)voidSetRadius(intr){radius=r;}intGetRadius(){returnradius;}voidShowRadius(){cout<<"BaseclassCircle:radius="<<radius<<endl;}private://Circle類私有數(shù)據(jù)成員intradius;//圓半徑};35第4章繼承與組合

classCylinder:privateCircle

{public://Cylinder類公用成員函數(shù)voidSetHeight(inth){height=h;}intGetHeight(){returnheight;}voidShowHeight(){

cout<<"DerivedclassCylinder:height="<<height<<endl;}voidSet(intr,inth){SetRadius(r);height=h;}voidShow(){cout<<"radius="<<GetRadius()<<endl;cout<<"height="<<height<<endl;}private://Cylinder類私有數(shù)據(jù)成員intheight;//圓柱體高度};

intmain()

{Cylinderobj;//obj.SetRadius(10);//obj.ShowRadius();obj.SetHeight(20);obj.ShowHeight();obj.Set(30,40);obj.Show();

return0;

}第4章繼承與組合3738私有繼承舉例classPoint //基類Point類的聲明{public: //公有函數(shù)成員

voidInitP(floatxx=0,floatyy=0){X=xx;Y=yy;} voidMove(floatxOff,floatyOff){X+=xOff;Y+=yOff;} floatGetX(){returnX;} floatGetY(){returnY;}private: //私有數(shù)據(jù)成員

floatX,Y;};39私有繼承舉例classRectangle:privatePoint //派生類聲明{public: //新增外部接口

voidInitR(floatx,floaty,floatw,floath) {InitP(x,y);W=w;H=h;} //訪問基類公有成員

voidMove(floatxOff,floatyOff){Point::Move(xOff,yOff);} floatGetX(){returnPoint::GetX();} floatGetY(){returnPoint::GetY();} floatGetH(){returnH;} floatGetW(){returnW;}private: //新增私有數(shù)據(jù)

floatW,H;};//floatGetX(){returnPoint::GetX();}//floatGetY(){returnPoint::GetY();}40intmain(){//通過派生類對(duì)象只能訪問本類成員

Rectanglerect; rect.InitR(2,3,20,10); rect.Move(3,2); cout<<rect.GetX()<<','<<rect.GetY()<<',' <<rect.GetH()<<','<<rect.GetW()<<endl; return0;}40私有繼承舉例復(fù)習(xí)有類Point如下:classPoint //基類Point類的聲明{public: //公有函數(shù)成員

voidInitP(floatxx=0,floatyy=0){X=xx;Y=yy;} voidMove(floatxOff,floatyOff){X+=xOff;Y+=yOff;} floatGetX(){returnX;} floatGetY(){returnY;}private: //私有數(shù)據(jù)成員

floatX,Y;};以Point為父類,定義一個(gè)子類Circle類,繼承方式為私有繼承,Circle類中新增私有數(shù)據(jù)成員r和公有成員函數(shù)GetR()和InitC(),要求在main()函數(shù)中,子類對(duì)象能夠使用InitP(),Move(),GetX(),GetY()和GetR()。由protected聲明的成員稱為“受保護(hù)的成員”,簡(jiǎn)稱“保護(hù)成員”。從類的用戶角度來看,保護(hù)成員等價(jià)于私有成員。但有一點(diǎn)與私有成員不同,保護(hù)成員可以被派生類的成員函數(shù)訪問。4.4.3保護(hù)成員和保護(hù)繼承第4章繼承與組合42在定義一個(gè)派生類時(shí)將基類的繼承方式指定為protected的,稱為保護(hù)繼承。用保護(hù)繼承方式建立的派生類稱為保護(hù)派生類(protectedderivedclass),其基類稱為受保護(hù)的基類(protectedbaseclass),簡(jiǎn)稱保護(hù)基類。4.4.3保護(hù)成員和保護(hù)繼承第4章繼承與組合43第4章繼承與組合表4-3基類成員在派生類中的訪問屬性4.4.3保護(hù)成員和保護(hù)繼承基類中的成員在公用派生類中的訪問屬性在私有派生類中的訪問屬性在保護(hù)派生類中的訪問屬性私有成員不可訪問不可訪問不可訪問公用成員公用私有保護(hù)保護(hù)成員保護(hù)私有保護(hù)44通過以上的介紹,可以知道:(1)在派生類中,成員有4種不同的訪問屬性:①公用的:派生類內(nèi)和派生類外都可以訪問。②受保護(hù)的:派生類內(nèi)可以訪問,派生類外不能訪問,其下一層的派生類可以訪問。③私有的:派生類內(nèi)可以訪問,派生類外不能訪問。④不可訪問的:派生類內(nèi)和派生類外都不能訪問。4.4.3保護(hù)成員和保護(hù)繼承第4章繼承與組合45第4章繼承與組合表4-4派生類中的成員的訪問屬性派生類中的成員在派生類中在派生類外在下層公用派生類中派生類中訪問屬性為公用的成員可以可以可以派生類中訪問屬性為受保護(hù)的成員可以不可以可以派生類中訪問屬性為私有的成員可以不可以不可以在派生類中不可訪問的成員不可以不可以不可以46(2)類的成員在不同作用域中有不同的訪問屬性,對(duì)這一點(diǎn)要十分清楚。4.4.3保護(hù)成員和保護(hù)繼承第4章繼承與組合47第4章繼承與組合【例4-3】保護(hù)繼承的例子。48classCircle//聲明基類Circle——圓類{public://Circle類公用成員函數(shù)voidSetRadius(intr){radius=r;}intGetRadius(){returnradius;}voidShowRadius(){cout<<"BaseclassCircle:radius="<<radius<<endl;}private://Circle類私有數(shù)據(jù)成員intradius;//圓半徑};第4章繼承與組合//以protected方式聲明保護(hù)派生類CylinderclassCylinder:protectedCircle{public://Cylinder類公用成員函數(shù)voidSetHeight(inth){height=h;}intGetHeight(){returnheight;}voidShowHeight(){cout<<"DerivedclassCylinder:height="<<height<<endl;}voidSet(intr,inth){SetRadius(r);height=h;}voidShow(){cout<<"radius="<<GetRadius()<<endl;cout<<"height="<<height<<endl;}private://Cylinder類私有數(shù)據(jù)成員intheight;//圓柱體高度};

intmain()

{Cylinderobj;//obj.SetRadius(10);//obj.ShowRadius();obj.SetHeight(20);obj.ShowHeight();obj.Set(30,40);obj.Show();

return0;

}第4章繼承與組合5051保護(hù)繼承舉例classPoint //基類Point類的聲明{public: //公有函數(shù)成員

voidInitP(floatxx=0,floatyy=0){X=xx;Y=yy;} voidMove(floatxOff,floatyOff){X+=xOff;Y+=yOff;} floatGetX(){returnX;} floatGetY(){returnY;}private: //私有數(shù)據(jù)成員

floatX,Y;};52保護(hù)繼承舉例classRectangle:protectedPoint //派生類聲明{public: //新增外部接口

voidInitR(floatx,floaty,floatw,floath) {InitP(x,y);W=w;H=h;} //訪問基類公有成員

floatGetH(){returnH;} floatGetW(){returnW;}private: //新增私有數(shù)據(jù)

floatW,H;};floatGetX(){returnPoint::GetX();}floatGetY(){returnPoint::GetY();}voidMove(floatxOff,floatyOff){Point::Move(xOff,yOff);}53intmain(){Rectanglerect; rect.InitR(2,3,20,10); rect.Move(3,2); cout<<rect.GetX()<<','<<rect.GetY()<<',' <<rect.GetH()<<','<<rect.GetW()<<endl; return0;}53錯(cuò)誤,不能在類外通過派生類的對(duì)象來訪問基類的成員函數(shù)Move()、GetX()和GetY()保護(hù)繼承舉例54classB:publicA//public方式{public:voidf3();protected:voidf4();private:intm;};classC:protectedB//protected方式{public:voidf5();private:intn;};classA{public:inti;protected:voidf2();intj;private:intk;};練習(xí)P134第一題55在前面介紹派生類的構(gòu)成時(shí)曾提到:可以在派生類中聲明一個(gè)與基類成員同名的成員,則派生類的新成員會(huì)屏蔽與其同名的基類成員,使同名的基類成員成為“不可見”的,即基類成員的名字被隱藏。4.4.4派生類對(duì)基類成員的重定義

和名字隱藏第4章繼承與組合56第4章繼承與組合【例4-4】派生類重定義基類成員函數(shù)的例子。#include<iostream>usingnamespacestd;classCircle

//聲明基類Circle{public://基類Circle的公用成員函數(shù)voidSet(intr){radius=r;}voidShow(){cout<<"BaseclassCircle:radius="<<radius<<endl;}private://基類Circle的私有數(shù)據(jù)成員intradius;//圓半徑};57第4章繼承與組合classCylinder:publicCircle{public:voidSet(intr,inth){Base::Set(r);height=h;}voidShow(){Base::Show();cout<<"DerivedclassCylinder:height=“<<height<<endl;}private:intheight;};58

intmain()

{Cylinderobj;obj.Set(10,20);obj.Show();//obj.Set(10);

obj.Circle::Set(30);obj.Circle::Show();return0;}第4章繼承與組合59從上例可以看出:(1)如果是在派生類中聲明了一個(gè)與基類成員函數(shù)名字相同,參數(shù)也相同的成員函數(shù),則基類中的成員函數(shù)將被隱藏。(2)如果是在派生類中聲明了一個(gè)與基類成員函數(shù)名字相同,但參數(shù)不同的成員函數(shù),則基類中的成員函數(shù)也將被隱藏。4.4.4派生類對(duì)基類成員的重定義和名字隱藏第4章繼承與組合60第4章繼承與組合【例】派生類重定義基類數(shù)據(jù)成員的例子。#include<iostream>usingnamespacestd;classBase

//聲明基類{public://基類公用成員

floaty;voidset(intn){x=n;}voidshow(){cout<<"Baseclass:x="<<x<<endl;}private://基類私有成員

intx;};61第4章繼承與組合//以public方式聲明派生類Derived

class

Derived:public

Base{public:voidset(inti,intj,intk){Base::set(i);y=j;z=k;}voidshow(){Base::show();cout<<"Baseclass:y="<<Base::y<<endl;cout<<"Derivedclass:y="<<y<<endl;cout<<"Derivedclass:z="<<z<<endl;}private:inty,z;};62

intmain()

{Derivedobj;

obj.set(1,2,3);

obj.Base::y=12.3;

obj.show();

return0;

}第4章繼承與組合程序運(yùn)行結(jié)果如下:Baseclass:x=1Baseclass:y=12.3Derivedclass:y=2Derivedclass:z=363由于基類的構(gòu)造函數(shù)和析構(gòu)函數(shù)派生類是不能繼承的。在聲明派生類時(shí),一般還應(yīng)當(dāng)自己定義派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)。4.5派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)第4章繼承與組合64構(gòu)造函數(shù)的作用是在創(chuàng)建對(duì)象時(shí)對(duì)對(duì)象的數(shù)據(jù)成員進(jìn)行初始化。派生類數(shù)據(jù)成員包括從基類繼承過來的數(shù)據(jù)成員和自己新增加的數(shù)據(jù)成員,在設(shè)計(jì)派生類的構(gòu)造函數(shù)時(shí),不僅要考慮派生類新增數(shù)據(jù)成員的初始化,還應(yīng)當(dāng)考慮對(duì)其從基類繼承過來的數(shù)據(jù)成員的初始化。采取的方法是在執(zhí)行派生類的構(gòu)造函數(shù)時(shí),調(diào)用基類的構(gòu)造函數(shù)。4.5.1派生類構(gòu)造函數(shù)第4章繼承與組合65下面從最簡(jiǎn)單的派生類構(gòu)造函數(shù)的定義說起。所謂簡(jiǎn)單的派生類是指只有一個(gè)基類,而且只有一級(jí)派生,在派生類的數(shù)據(jù)成員中不包含其他類對(duì)象的派生類。簡(jiǎn)單的派生類構(gòu)造函數(shù)的定義請(qǐng)看下面這個(gè)例子:4.5.1派生類構(gòu)造函數(shù)第4章繼承與組合66第4章繼承與組合【例4-5】簡(jiǎn)單派生類的構(gòu)造函數(shù)。#include<iostream>usingnamespacestd;classPerson//聲明基類Person{public:Person(char*Name,charSex,intAge){strcpy(name,Name);sex=Sex;age=Age;cout<<"TheconstructorofbaseclassPersoniscalled."<<endl;}~Person()//基類析構(gòu)函數(shù){cout<<"ThedestructorofbaseclassPersoniscalled."<<endl;}voidShow(){cout<<"Theperson’sname:"<<name<<endl;cout<<"sex:"<<sex<<endl;cout<<"age:"<<age<<endl;}protected://基類的保護(hù)數(shù)據(jù)成員charname[11];charsex;intage;};67第4章繼承與組合classStudent:publicPerson{public:Student(char*Name,charSex,intAge,char*Id,char*Date,floatScore):Person(Name,Sex,Age){strcpy(id,Id);strcpy(date,Date);score=Score;cout<<"TheconstructorofderivedclassStudentiscalled."<<endl;}~Student()//派生類析構(gòu)函數(shù){cout<<"ThedestructorofderivedclassStudentiscalled."<<endl;}voidStuShow(){……}protected:charid[12];//學(xué)號(hào),固定為11位chardate[11];//入學(xué)時(shí)間floatscore;};68intmain(){Studentstu("Mary",'F',19,"20120101001","2012.09.01",680);stu.StuShow();

return0;}第4章繼承與組合69上例中派生類Student的構(gòu)造函數(shù)有6個(gè)形參,前3個(gè)作為調(diào)用基類構(gòu)造函數(shù)的實(shí)參,后3個(gè)為對(duì)派生類新增數(shù)據(jù)成員z初始化所需要的參數(shù)。其關(guān)系如圖4-4所示。4.5.1派生類構(gòu)造函數(shù)第4章繼承與組合圖4-4派生類Student的構(gòu)造函數(shù)的參數(shù)傳遞70定義簡(jiǎn)單派生類構(gòu)造函數(shù)的一般形式為:派生類名::派生類名(基類所需的形參,本類成員所需的形參):基類名(參數(shù)表){

派生類成員初始化賦值語句;};4.5.1派生類構(gòu)造函數(shù)第4章繼承與組合71在建立一個(gè)對(duì)象時(shí),執(zhí)行構(gòu)造函數(shù)的順序是:(1)最先調(diào)用基類的構(gòu)造函數(shù),對(duì)基類數(shù)據(jù)成員初始化。(2)再執(zhí)行派生類構(gòu)造函數(shù)的函數(shù)體,對(duì)派生類新增數(shù)據(jù)成員初始化。4.5.1派生類構(gòu)造函數(shù)第4章繼承與組合72在使用派生類構(gòu)造函數(shù)時(shí),還有以下幾種情況:(1)多級(jí)派生的構(gòu)造函數(shù)。一個(gè)類不僅可以派生出一個(gè)派生類,派生類還可以繼續(xù)派生,形成派生的層次結(jié)構(gòu)。在派生的層次結(jié)構(gòu)中,每一層派生類的構(gòu)造函數(shù)只負(fù)責(zé)調(diào)用其上一層(即它的直接基類)的構(gòu)造函數(shù)。4.5.1派生類構(gòu)造函數(shù)第4章繼承與組合734.5.1派生類構(gòu)造函數(shù)第4章繼承與組合74classGraduate:publicStudent{public:Graduate(char*Name,charSex,intAge,char*Id,char*Date,floatScore,char*Direct,char*Teacher):Student(Name,Sex,Age,Id,Date,Score){strcpy(direct,Direct);strcpy(teacher,Teacher);cout<<"TheconstructorofderivedclassGraduateiscalled."<<endl;}voidGradShow(){StuShow();cout<<"direct:"<<direct<<endl;cout<<"teachername:"<<teacher<<endl;}~Graduate(){cout<<"ThedestructorofderivedclassGraduateiscalled.“<<endl;}protected://派生類的保護(hù)數(shù)據(jù)成員chardirect[21];charteacher[11];};(2)當(dāng)不需要對(duì)派生類新增的成員進(jìn)行任何初始化操作時(shí),派生類構(gòu)造函數(shù)的函數(shù)體可以為空,即構(gòu)造函數(shù)是空函數(shù),如在派生類Derived的構(gòu)造函數(shù)可以改寫為:

Derived(intm,intn,intk):Base(m,n){}此派生類構(gòu)造函數(shù)的作用只是為了將參數(shù)傳遞給基類構(gòu)造函數(shù),并在執(zhí)行派生類構(gòu)造函數(shù)時(shí)調(diào)用基類構(gòu)造函數(shù)。4.5.1派生類構(gòu)造函數(shù)第4章繼承與組合75(3)如果基類中沒有定義構(gòu)造函數(shù),或定義了沒有參數(shù)的構(gòu)造函數(shù),那么在定義派生類構(gòu)造函數(shù)時(shí)可以不寫基類構(gòu)造函數(shù)。在調(diào)用派生類構(gòu)造函數(shù)時(shí),系統(tǒng)會(huì)自動(dòng)調(diào)用基類的默認(rèn)構(gòu)造函數(shù)。第4章繼承與組合76#include<iostream>usingnamespacestd;classBase{public:Base(){x=0;y=0;}~Base(){}

protected:

intx,y;};class

Derived:publicBase{public:

Derived(intk)

{z=k;}~Derived(){}private:intz;};如果在基類中既定義了無參的構(gòu)造函數(shù),又定義了有參的構(gòu)造函數(shù)(構(gòu)造函數(shù)的重載),則在定義派生類構(gòu)造函數(shù)時(shí),既可以包含基類構(gòu)造函數(shù)及其參數(shù),亦可以不包含基類構(gòu)造函數(shù)。在調(diào)用派生類構(gòu)造函數(shù)時(shí),根據(jù)構(gòu)造函數(shù)的內(nèi)容決定調(diào)用基類的有參的構(gòu)造函數(shù)還是無參的構(gòu)造函數(shù)。我們可以根據(jù)派生類的需要決定采用哪一種方式。第4章繼承與組合7778說明派生類構(gòu)造函數(shù)在類外定義時(shí),在類內(nèi)中只寫該函數(shù)的聲明:

Derived(intm,intn,intk);在類外面定義派生類的構(gòu)造函數(shù):

Derived::Derived(intm,intn,intk):Base(m,n){z=k;}注意:在類中對(duì)派生類構(gòu)造函數(shù)作聲明時(shí),不包括基類構(gòu)造函數(shù)及其參數(shù)表列。只在定義函數(shù)時(shí)才將它列出。和構(gòu)造函數(shù)一樣,基類的析構(gòu)函數(shù)派生類也不能繼承。在聲明派生類時(shí),可以根據(jù)需要定義自己的析構(gòu)函數(shù),用來對(duì)派生類中新增加的成員進(jìn)行清理工作。在執(zhí)行派生類的析構(gòu)函數(shù)時(shí),系統(tǒng)會(huì)自動(dòng)調(diào)用基類的析構(gòu)函數(shù),對(duì)基類進(jìn)行清理。派生類析構(gòu)函數(shù)的執(zhí)行順序與構(gòu)造函數(shù)正好相反:(1)最先執(zhí)行派生類的析構(gòu)函數(shù)的函數(shù)體,對(duì)派生類新增加的成員進(jìn)行清理。(2)再調(diào)用基類的析構(gòu)函數(shù),對(duì)基類進(jìn)行清理。4.5.2派生類析構(gòu)函數(shù)第4章繼承與組合79第4章繼承與組合【例4-6】派生類的析構(gòu)函數(shù)。#include<iostream>usingnamespacestd;classPerson//聲明基類Person{public:Person(char*Name,charSex,intAge){name=newchar[strlen(Name)+1];strcpy(name,Name);sex=Sex;age=Age;cout<<"TheconstructorofbaseclassPersoniscalled."<<endl;}~Person()//基類析構(gòu)函數(shù){deletename;cout<<"ThedestructorofbaseclassPersoniscalled."<<endl;}protected://基類的保護(hù)數(shù)據(jù)成員char*name;charsex;intage;};80第4章繼承與組合classStudent:publicPerson

{public:Student(char*Name,charSex,intAge,char*Id,char*Date,floatScore):Person(Name,Sex,Age){id=newchar[strlen(Id)+1];strcpy(id,Id);date=newchar[strlen(Date)+1];strcpy(date,Date);score=Score;cout<<"TheconstructorofderivedclassStudentiscalled."<<endl;}~Student()//派生類析構(gòu)函數(shù){deleteid;deletedate;cout<<"ThedestructorofderivedclassStudentiscalled."<<endl;}protected:char*id;char*date;floatscore;};81第4章繼承與組合intmain(){Studentstu("Mary",'F',19,"20120101001","2012.09.01",680);return0;}82【例4-6】派生類的析構(gòu)函數(shù)。TheconstructorofbaseclassPersoniscalled.TheconstructorofderivedclassStudentiscalled.ThedestructorofderivedclassStudentiscalled.ThedestructorofbaseclassPersoniscalled.83單一繼承時(shí)的構(gòu)造函數(shù)舉例#include<iostream>usingnamespacestd;classB{public: B(); B(inti); ~B(); voidPrint()const;private: intb;};84B::B(){ b=0; cout<<"B'sdefaultconstructorcalled."<<endl;}B::B(inti){ b=i;cout<<"B'sconstructorcalled."<<endl;}B::~B(){ cout<<"B'sdestructorcalled."<<endl;}voidB::Print()const{ cout<<b<<endl;}8485classC:public

B{public:C(); C(inti,intj); ~C(); voidPrint()const; private: intc;};8586C::C(){ c=0; cout<<"C'sdefaultconstructorcalled."<<endl;}C::C(inti,intj):B(i){ c=j; cout<<"C'sconstructorcalled."<<endl;}C::~C(){ cout<<"C'sdestructorcalled."<<endl;}voidC::Print()const{ B::Print(); cout<<c<<endl;}intmain(){ Cobj(5,6); obj.Print();}8687運(yùn)行結(jié)果B'sconstructorcalled.C'sconstructorcalled.56C'sdestructorcalled.B'sdestructorcalled.練習(xí)有一個(gè)父類名為Point,有帶兩個(gè)參數(shù)的構(gòu)造函數(shù),如下:

classPoint{public:Point(intx1,inty1){x=x1;y=y1;}Point(){x=0;y=0;}……priate:intx,y;};要求:寫一個(gè)派生類名為Circle,寫出構(gòu)造函數(shù)的定義88多重繼承(multipleinheritance,MI)是指派生類具有兩個(gè)或兩個(gè)以上的直接基類(directclass)。4.6多重繼承第4章繼承與組合89多重繼承派生類的聲明格式如下:class<派生類名>:<繼承方式><基類名1>,…,<繼承方式><基類名n>{<派生類新增加成員>};注意:每一個(gè)“繼承方式”,只用于限制對(duì)緊隨其后之基類的繼承。不同的基類可以選擇不同的繼承方式。4.6.1聲明多重繼承的方法第4章繼承與組合9091多繼承舉例classA{public:voidsetA(int);voidshowA();private:inta;};classB{public:voidsetB(int);voidshowB();private:intb;};classC:publicA,privateB{public:voidsetC(int,int,int);voidshowC();private:intc;};92voidA::setA(intx){a=x;}voidB::setB(intx){b=x;}voidC::setC(intx,inty,intz){//派生類成員直接訪問基類的

//公有成員

setA(x);setB(y);c=z;}//其他函數(shù)實(shí)現(xiàn)略intmain(){Cobj;obj.setA(5);obj.showA();obj.setC(6,7,9);obj.showC();//obj.setB(6);錯(cuò)誤//obj.showB();錯(cuò)誤

return0;}在多重繼承方式下,定義派生類構(gòu)造函數(shù)的一般形式如下:<派生類名>(<總參數(shù)列表>):<基類名1>(<參數(shù)表1>),…,<基類名n>(<參數(shù)表n>){<派生類新增數(shù)據(jù)成員的初始化>};其中,<總參數(shù)表>必須包含完成所有基類數(shù)據(jù)成員初始化所需的參數(shù)。4.6.2多重繼承派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)第4章繼承與組合93在建立一個(gè)派生類對(duì)象時(shí),構(gòu)造函數(shù)調(diào)用順序?yàn)椋?/p>

先調(diào)用所有基類的構(gòu)造函數(shù),再執(zhí)行派生類構(gòu)造函數(shù)的函數(shù)體。所有基類構(gòu)造函數(shù)的調(diào)用順序?qū)凑账鼈冊(cè)诶^承方式中的聲明次序調(diào)用,而不是按派生類構(gòu)造函數(shù)參數(shù)初始化列表中的次序調(diào)用。4.6.2多重繼承派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)第4章繼承與組合94第4章繼承與組合【例4-7】多重繼承派生類的構(gòu)造函數(shù)。95#include<iostream>usingnamespacestd;classPerson//聲明基類Person{public:Person(char*Name,charSex,intAge){name=newchar[strlen(Name)+1];strcpy(name,Name);sex=Sex;age=Age;cout<<"TheconstructorofbaseclassPersoniscalled."<<endl;}~Person()//基類析構(gòu)函數(shù){deletename;cout<<"ThedestructorofbaseclassPersoniscalled."<<endl;}protected://基類的保護(hù)數(shù)據(jù)成員char*name;charsex;intage;};第4章繼承與組合classStudent:publicPerson

{public:Student(char*Name,charSex,intAge,char*Id,char*Date,floatScore):Person(Name,Sex,Age){id=newchar[strlen(Id)+1];strcpy(id,Id);date=newchar[strlen(Date)+1];strcpy(date,Date);score=Score;cout<<"TheconstructorofderivedclassStudentiscalled."<<endl;}~Student()//派生類析構(gòu)函數(shù){deleteid;deletedate;cout<<"ThedestructorofderivedclassStudentiscalled."<<endl;}protected:char*id;char*date;floatscore;};4.5.1派生類構(gòu)造函數(shù)第4章繼承與組合97classGraduate:publicStudent{public:Graduate(char*Name,charSex,intAge,char*Id,char*Date,floatScore,char*Direct,char*Teacher):Student(Name,Sex,Age,Id,Date,Score){strcpy(direct,Direct);strcpy(teacher,Teacher);cout<<"TheconstructorofderivedclassGraduateiscalled."<<endl;}voidGradShow(){StuShow();cout<<"direct:"<<direct<<endl;cout<<"teachername:"<<teacher<<endl;}~Graduate(){cout<<"ThedestructorofderivedclassGraduateiscalled.“<<endl;}protected://派生類的保護(hù)數(shù)據(jù)成員chardirect[21];charteacher[11];};第4章繼承與組合classEmployee:publicPerson{public:Employee(char*Name,charSex,intAge,char*Num,char*Clerk,char*Depart,char*Timer):Person(Name,Sex,Age)//派生類構(gòu)造函數(shù){strcpy(num,Num);strcpy(clerk,Clerk);strcpy(department,Depart);strcpy(timer,Timer);cout<<"TheconstructorofderivedclassEmployeeiscalled."<<endl;}~Employee(){……}voidEShow(){……}voidEmpShow(){……}protected://派生類的保護(hù)數(shù)據(jù)成員charnum[8];charclerk[21];chardepartment[31];chartimer[11];};98第4章繼承與組合classGradOnWork:publicGraduate,publicEmployee

{public:GradOnWork(char*Name,charSex,intAge,char*Id,char*Date,floatScore,char*Direct,char*Teacher,char*Num,char*Clerk,char*Depart,char*Timer):Graduate(Name,Sex,Age,Id,Date,Score,Direct,Teacher),Employee(Name,Sex,Age,Num,Clerk,Depart,Timer){cout<<"TheconstructorofderivedclassGradOnWorkiscalled."<<endl;}~GradOnWork(){……}voidGWShow(){……}};99第4章繼承與組合intmain(){GradOnWorkgw("Mary",'F',19,"20120101001","2012.09.01",680,"Computer","Johnson","JG01029","SeniorEngineer","ResearchDepartment","20years");gw.GWShow();return0;}100在派生類的析構(gòu)函數(shù)問題上,多重繼承方式也與單繼承方式類似。派生類析構(gòu)函數(shù)的執(zhí)行順序與其構(gòu)造函數(shù)執(zhí)行順序正好相反,首先執(zhí)行派生類析構(gòu)函數(shù)的函數(shù)體,對(duì)派生類新增的數(shù)據(jù)成員進(jìn)行清理;然后調(diào)用基類的析構(gòu)函數(shù),對(duì)從基類繼承來的成員進(jìn)行清理。所有基類的析構(gòu)函數(shù)將按照它們?cè)诶^承方式中的聲明次序的逆序、從右到左調(diào)用。4.6.2多重繼承派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)第4章繼承與組合101102二義性問題舉例classA{public:voidf();intx;};classB{public:voidf();voidg();intx;};classC:publicA,piblicB{public:voidg();voidh();};如果聲明:Cc1;則c1.f();c1.g();cout<<c1.x;在多重繼承方式下,派生類繼承了多個(gè)基類的成員。如果在這多個(gè)基類中擁有同名的成員,那么,派生類在繼承各個(gè)基類的成員之后,當(dāng)調(diào)用該派生類的這些同名成員時(shí),由于成員標(biāo)識(shí)符不唯一,出現(xiàn)二義性,編譯器無法確定到底應(yīng)該選擇派生類中的哪一個(gè)成員,這種由于多重繼承而引起的對(duì)派生類的某個(gè)成員訪問出現(xiàn)不唯一的情況就稱為二義性問題。4.6.3多重繼承引起的二義性問題第4章繼承與組合103二義性主要分為3種類型:(1)兩個(gè)基類有同名成員;(2)兩個(gè)基類和派生類三者都有同名成員;(3)如果兩個(gè)基類Base1和Base2是從同一個(gè)基類Base派生的。4.6.3多重繼承引起的二義性問題第4章繼承與組合104第4章繼承與組合(1)兩個(gè)基類有同名成員#include<iostream>usingnamespacestd;classBase1

//聲明基類Base1{public://公用部分

intx;voiddisplay(){cout<<"Base1::x="<<x<<endl;}};classBase2

//聲明基類Base2{public://公用部分

intx;voiddisplay(){cout<<"Base2::x="<<x<<endl;}};105第4章繼承與組合class

Derived:public

Base1,public

Base2{public:inty;voidshow(){cout<<“Base1::x=”<<Base1::x<<endl;

//Base1::display();

cout<<"Base2::x="<<Base2::x<<endl;

//Base2::display();cout<<"Derived::y="<<y<<endl;

}};106第4章繼承與組合intmain(){

Derivedobj;obj.x=8;//錯(cuò)誤

obj.display();//錯(cuò)誤

return0;}107編譯此程序,出現(xiàn)如下錯(cuò)誤和警告提示:errorC2385:'Derived::x'isambiguouswarningC4385:couldbethe'x'inbase'Base1'ofclass'Derived'warningC4385:orthe'x'inbase'Base2'ofclass'Derived'errorC2385:'Derived::display'isambiguouswarningC4385:couldbethe'display'inbase'Base1'ofclass'Derived'warningC4385:orthe'display'inbase'Base2'ofclass'Derived'4.6.3多重繼承引起的二義性問題第4章繼承與組合108由于基類Base1和Base2都有數(shù)據(jù)成員x和成員函數(shù)display(),編譯系統(tǒng)無法識(shí)別要訪問的是哪一個(gè)基類的成員,因此程序編譯出錯(cuò)。解決此類問題可以用基類名來限定,即寫成:obj.Base1::x=3;obj

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝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ù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 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)論