算法的設(shè)計(jì)與基礎(chǔ)課件_第1頁(yè)
算法的設(shè)計(jì)與基礎(chǔ)課件_第2頁(yè)
算法的設(shè)計(jì)與基礎(chǔ)課件_第3頁(yè)
算法的設(shè)計(jì)與基礎(chǔ)課件_第4頁(yè)
算法的設(shè)計(jì)與基礎(chǔ)課件_第5頁(yè)
已閱讀5頁(yè),還剩84頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

程序設(shè)計(jì)是計(jì)算機(jī)學(xué)科的核心和靈魂程序設(shè)計(jì)基礎(chǔ)第七章繼承機(jī)制

1程序設(shè)計(jì)是計(jì)算機(jī)學(xué)科的核心和靈魂程序設(shè)計(jì)基礎(chǔ)第七章繼承機(jī)制繼承機(jī)制的作用繼承成員的訪問控制規(guī)則繼承成員的調(diào)整類型兼容性類層次中的構(gòu)造函數(shù)與析構(gòu)函數(shù)多重繼承重復(fù)繼承2繼承機(jī)制的作用2§7.1繼承的基本概念7.1.1IS-A關(guān)系

IS-A關(guān)系:組織和表達(dá)知識(shí),將知識(shí)組織成為一種有層次、可分類的結(jié)構(gòu)。鴨梨是一種(IS-A))梨。鴨梨具有梨都具有的特征;鴨梨與其他梨有不同的特征。動(dòng)物分類:界(kingdom)、門(phylum)、綱(class)、目(order)、科(family)、屬(genus)、種(species)。3§7.1繼承的基本概念7.1.1IS-A關(guān)系

IS-A關(guān)§7.1繼承的基本概念7.1.2繼承機(jī)制

繼承(inheritance):在一個(gè)類或若干已知類的基礎(chǔ)上,經(jīng)過適當(dāng)?shù)男薷?、擴(kuò)充構(gòu)成一個(gè)新類,這個(gè)新類具有原來作為基礎(chǔ)類的特征。繼承是面向?qū)ο蟪绦蛩赜械奶卣?。如果類B繼承類A,則類B自動(dòng)包括了類A中定義的數(shù)據(jù)成員和成員函數(shù),還可定義類B自己的成員;稱類A為類B的父類(parent)、超類(super-class)或基類(base);類B稱為類A的子類(child)或派生類(derived-class);祖先類(ancestor):包括了其父類及其父類的祖先類。后代類(descendant):包括了其子類以及子類的后代類。4§7.1繼承的基本概念7.1.2繼承機(jī)制

繼承(inhe§7.1繼承的基本概念7.1.2繼承機(jī)制

類的圖形表示(UML):類名類名類名類名屬性屬性行為行為具體抽象5§7.1繼承的基本概念7.1.2繼承機(jī)制

類的圖形表示(§7.1繼承的基本概念7.1.2繼承機(jī)制

類層次表示(UML):秦冠蘋果國(guó)光蘋果水果蘋果梨紅富士蘋果6§7.1繼承的基本概念7.1.2繼承機(jī)制

類層次表示(U§7.1繼承的基本概念7.1.2繼承機(jī)制

IS-A與HAS-A…輪胎汽車真空輪胎輪胎7§7.1繼承的基本概念7.1.2繼承機(jī)制

IS-A與HA§7.1繼承的基本概念7.1.3繼承的作用

繼承機(jī)制的雙重作用:類的構(gòu)造機(jī)制:繼承通過擴(kuò)充、組合先有類來構(gòu)造新的類。擴(kuò)充:形成先有類的特例——派生類;組后:抽取若干現(xiàn)有類的共性形成新的抽象層次——基類。

類的構(gòu)造機(jī)制:如果類B繼承類A,則要求對(duì)象為A類型的地方也可以接受B類型的對(duì)象。7.1.4繼承與軟件重用

軟件重用:重用專家的經(jīng)驗(yàn);重用標(biāo)準(zhǔn)的設(shè)計(jì)與算法;

重用類庫(kù)與過程(函數(shù))庫(kù);重用語言和操作系統(tǒng)中內(nèi)置的強(qiáng)大的命令;重用框架;重用完整的應(yīng)用(程序)。重用程序源代碼:利用繼承機(jī)制組織類之間的組織關(guān)系;派生類具有調(diào)節(jié)所繼承的屬性和行為的能力;提高程序可靠性。8§7.1繼承的基本概念7.1.3繼承的作用

繼承機(jī)制的雙§7.1繼承的基本概念7.1.5C++繼承常見的幾種形式

DABCABCABCD單重繼承多重繼承重復(fù)繼承9§7.1繼承的基本概念7.1.5C++繼承常見的幾種形式§7.2C++的繼承機(jī)制7.2.1繼承的語法繼承是類與類之間的一種關(guān)系定義:“類B繼承類A”,

或者說“類A派生類B”

圖解為:

則在類B中除了自己定義的成員之外,還自動(dòng)包括了類A中定義的數(shù)據(jù)成員與成員函數(shù),這些自動(dòng)繼承下來的成員稱為類B的繼承成員。

BA基類派生類10§7.2C++的繼承機(jī)制7.2.1繼承的語法BA基類派生7.2.1繼承的語法繼承的語法class派生類名:基類類名表{ public: 公有成員說明列表; protected:受保護(hù)成員說明列表; private: 私有成員說明列表;};其中基類類名表的格式為:

access基類類名1,……,access基類類名naccess為繼承訪問控制符,規(guī)定了派生類對(duì)基類的繼承方式,可為public,private或者protected,繼承訪問控制符可省略,此時(shí)認(rèn)為是private§7.2C++的繼承機(jī)制117.2.1繼承的語法§7.2C++的繼承機(jī)制11classBASE{……};classA:publicBASE{ …… //單繼承};classB:privateBASE,publicD{…… //多重繼承};classC:publicA,B{……};BASEABDBASEC私有派生§7.2C++的繼承機(jī)制7.2.1繼承的語法12classBASE{BASEABDBASEC私有派生§7§7.2C++的繼承機(jī)制7.2.1繼承的語法保護(hù)訪問控制屬性:protected在protected后定義的是保護(hù)段,其中的數(shù)據(jù)成員或成員函數(shù)稱為受保護(hù)成員:具有公有成員與私有成員的雙重角色。一個(gè)類的受保護(hù)成員,對(duì)于其子孫類(派生類)的成員函數(shù)來說是公有的,對(duì)類本身及后代類之外定義的其他函數(shù)則是私有成員。

例:classBASE{private:intx;protected:inti,j;};classD:publicBASE{ voidmake(); }; voidD::make() {intk=i*j;……}成員訪問控制類自身派生類其他類public可訪問可訪問可訪問protected可訪問可訪問不可訪問private可訪問不可訪問不可訪問13§7.2C++的繼承機(jī)制7.2.1繼承的語法成員訪問控制7.2.1繼承的語法派生類可以重新定義基類的成員函數(shù),覆蓋基類的同名函數(shù)例:classDATE{public: DATE(intyy=0,intmm=0,intdd=0);//構(gòu)造函數(shù) voidset_date(intyy,intmm,intdd);//設(shè)置日期 voidget_date(int&yy,int&mm,int&dd);//取日期

voidprint_date();//以ANSI格式(yy.mm.dd)打印日期protected: intyear,month,day; //年、月、日};voidDATE::print_date(){ cout<<year<<“.”<<month<<“.”<<day<<“\n”;}§7.2C++的繼承機(jī)制147.2.1繼承的語法§7.2C++的繼承機(jī)制147.2.1繼承的語法classEUROPE_DATE:publicDATE{public:

voidprint_date();//以歐洲格式(dd-mm-yy)打印日期 voidprint(intisANSI);};

voidEUROPE_DATE::print_date(){ //以歐洲格式(dd-mm-yy)打印日期 cout<<day<<“-”<<month<<“-”<<year<<“\n”;}§7.2C++的繼承機(jī)制157.2.1繼承的語法§7.2C++的繼承機(jī)制157.2.1繼承的語法通過類名限定符在派生類中使用基類的同名成員voidEUROPE_DATE::print(intisANSI){ if(isANSI) DATE::print_date(); else print_date();}voidmain(){ EUROPE_DATEtest; test.print_date(); //調(diào)用EUROPE_DATE中重定義的同名函數(shù) //以歐洲格式(dd-mm-yy)打印 test.DATE::print_date(); //以ANSI格式(yy.mm.dd)打印}§7.2C++的繼承機(jī)制167.2.1繼承的語法§7.2C++的繼承機(jī)制167.2.1繼承的語法//程序:TIME.HPP//功能:帶有日期信息的時(shí)間類的類界面ClassTIME:publicDATE{public:TIME(inthh,intmm,intss);voidset_time(inthh,intmm,intss);voidget_time(inthh,intmm,intss);voidprint_time();Protected:inthour,minute,second;};§7.2C++的繼承機(jī)制DATEEUROPE_DATETIME177.2.1繼承的語法§7.2C++的繼承機(jī)制DATEEU§7.2C++的繼承機(jī)制7.2.2繼承訪問控制規(guī)則公有繼承(公有派生)、私有繼承、保護(hù)繼承無論采用什么派生的方式,派生類中都不能訪問基類的私有成員繼承訪問控制基類成員訪問控制在派生類中的訪問控制publicpublicpublicprotectedprotectedprivate不可訪問protectedpublicprotectedprotectedprotectedprivate不可訪問privatepublicprivateprotectedprivateprivate不可訪問18§7.2C++的繼承機(jī)制7.2.2繼承訪問控制規(guī)則繼承訪7.2.2繼承訪問控制規(guī)則classBASE{ protected: inti,j; public: voidget_ij(); private: intx_temp;};classY1:publicBASE{ //公有派生:在Y1類中,i、j是受保護(hù)成員 floatyMember; //get_ij()是公有成員};classY2:protectedBASE{//保護(hù)派生:在Y2類中,i、j是受保護(hù)成員…… //get_ij()變成受保護(hù)成員};classY3:privateBASE{ //私有派生:在Y3類中,i、j、get_ij()都變…… //成私有成員};§7.2C++的繼承機(jī)制197.2.2繼承訪問控制規(guī)則§7.2C++的繼承機(jī)制197.2.3一個(gè)應(yīng)用繼承機(jī)制的完整例子簡(jiǎn)單圖形程序設(shè)計(jì)§7.2C++的繼承機(jī)制CPointintm_x;intm_y;int GetX();int GetY();CRectangleCPointm_cpLocation;intm_nWidth;intm_nHeight;intGetArea();intGetPerimeter();CPoint&GetPosition();CSquare

intGetEdge();207.2.3一個(gè)應(yīng)用繼承機(jī)制的完整例子§7.2C++的繼承7.2.3一個(gè)應(yīng)用繼承機(jī)制的完整例子#include<iostream.h>#include<conio.h>classCPoint{private:intm_x;intm_y;public:CPoint(int,int);int GetX();int GetY();};§7.2C++的繼承機(jī)制CPoint::CPoint(intx,inty){m_x=x;m_y=y;}intCPoint::GetX(){returnm_x;}intCPoint::GetY(){returnm_y;}217.2.3一個(gè)應(yīng)用繼承機(jī)制的完整例子§7.2C++的繼承7.2.3一個(gè)應(yīng)用繼承機(jī)制的完整例子classCRectangle//矩形類{public:CPointm_cpLocation; //圖形所在位置intm_nWidth; //圖形的寬度intm_nHeight; //圖形的高度CRectangle(intnX,intnY,intnWidth,intnHeight);intGetArea(); //求面積intGetPerimeter(); //求周長(zhǎng)CPoint&GetPosition(); //返回圖形位置};§7.2C++的繼承機(jī)制227.2.3一個(gè)應(yīng)用繼承機(jī)制的完整例子§7.2C++的繼承7.2.3一個(gè)應(yīng)用繼承機(jī)制的完整例子CRectangle::CRectangle(intnX,intnY,intnW,intnH):m_cpLocation(nX,nY){m_nWidth=nW;m_nHeight=nH;}intCRectangle::GetArea(){returnm_nWidth*m_nHeight;}intCRectangle::GetPerimeter(){returnm_nWidth+m_nWidth+m_nHeight+m_nHeight;}CPoint&CRectangle::GetPosition(){returnthis->m_cpLocation;}§7.2C++的繼承機(jī)制237.2.3一個(gè)應(yīng)用繼承機(jī)制的完整例子§7.2C++的繼承7.2.3一個(gè)應(yīng)用繼承機(jī)制的完整例子classCSquare:publicCRectangle//正方形類,派生自矩形類{public:CSquare(intnX,intnY,intnEdge);intGetEdge();//返回邊長(zhǎng)};CSquare::CSquare(intnX,intnY,intnEdge):CRectangle(nX,nY,nEdge,nEdge){}intCSquare::GetEdge(){returnm_nWidth;}§7.2C++的繼承機(jī)制247.2.3一個(gè)應(yīng)用繼承機(jī)制的完整例子§7.2C++的繼承7.2.3一個(gè)應(yīng)用繼承機(jī)制的完整例子voidmain(){CRectangler(1,1,2,3);CSquares(0,0,2);cout<<"Rectanglearea:"<<r.GetArea()<<endl;cout<<"Squarearea:"<<s.GetArea()<<endl;getch();}§7.2C++的繼承機(jī)制程序運(yùn)行結(jié)果:Rectanglearea:6Squarearea:4257.2.3一個(gè)應(yīng)用繼承機(jī)制的完整例子§7.2C++的繼承7.2.4派生類對(duì)象的存儲(chǔ)組織派生類的對(duì)象不僅存放了在派生類中定義的非靜態(tài)數(shù)據(jù)成員,而且也存放了從基類中繼承下來的非靜態(tài)數(shù)據(jù)成員。

例:classBASE{ protected: inti,j; public: voidget_ij(); private: intx_temp;};classY1:publicBASE{ floatyMember; };BASEobj1;Y1obj2;obj1iJx_temp函數(shù)指針obj2iJx_tempyMember函數(shù)指針§7.2C++的繼承機(jī)制267.2.4派生類對(duì)象的存儲(chǔ)組織obj1iobj2i§7.27.2.5類型兼容性

1.賦值運(yùn)算的類型兼容性類型的賦值兼容性規(guī)則允許將后代類的對(duì)象賦值給祖先類,但反之不成立。例:BASEobj1; Y1obj2; obj1=obj2;把obj2中基類部分的內(nèi)容賦給obj1 obj2=obj1;但此規(guī)則只適用于公有派生,只有公有派生類才能兼容基類類型§7.2C++的繼承機(jī)制277.2.5類型兼容性

1.賦值運(yùn)算的類型兼容性§7.2C7.2.5類型兼容性

指向基類對(duì)象的指針也可指向公有派生類對(duì)象BASE*p; Y1*p1;p=&obj1; p1=&obj1;p=&obj2; p1=&obj2; p=p1;2.參數(shù)傳遞與對(duì)象初始化的類型兼容性與賦值運(yùn)算類型兼容性相同§7.2C++的繼承機(jī)制287.2.5類型兼容性

§7.2C++的繼承機(jī)制28§7.3繼承與構(gòu)造函數(shù)、析構(gòu)函數(shù)7.3.1構(gòu)造函數(shù)與析構(gòu)函數(shù)的調(diào)用次序1.構(gòu)造函數(shù)的調(diào)用次序在創(chuàng)建一個(gè)派生類的對(duì)象時(shí)先調(diào)用其基類的構(gòu)造函數(shù)再調(diào)用本類對(duì)象成員的構(gòu)造函數(shù)最后才調(diào)用本類的構(gòu)造函數(shù)2.析構(gòu)函數(shù)的調(diào)用次序先調(diào)用本類的析構(gòu)函數(shù)再調(diào)用本類對(duì)象成員的析構(gòu)函數(shù)最后才調(diào)用其基類的析構(gòu)函數(shù)29§7.3繼承與構(gòu)造函數(shù)、析構(gòu)函數(shù)7.3.1構(gòu)造函數(shù)與析構(gòu)7.3.1構(gòu)造函數(shù)與析構(gòu)函數(shù)的調(diào)用次序#include<iostream.h>

classC{public: C()//構(gòu)造函數(shù) { cout<<"ConstructingCobject.\n"; }

~C()//析構(gòu)函數(shù) { cout<<"DestructingCobject.\n"; }};classBASE{public: BASE()//構(gòu)造函數(shù) { cout<<"Constructingbaseobject.\n"; } ~BASE()//析構(gòu)函數(shù) { cout<<"Destructingbaseobject.\n"; }};

§7.3繼承與構(gòu)造函數(shù)、析構(gòu)函數(shù)307.3.1構(gòu)造函數(shù)與析構(gòu)函數(shù)的調(diào)用次序§7.3繼承與構(gòu)造7.3.1構(gòu)造函數(shù)與析構(gòu)函數(shù)的調(diào)用次序classDERIVED:publicBASE{ C mOBJ;public: DERIVED()//構(gòu)造函數(shù) { cout<<"Constructingderivedobject.\n";} ~DERIVED()//析構(gòu)函數(shù) { cout<<"Destructingderivedobject.\n"; }};

intmain(){ DERIVEDobj;//聲明一個(gè)派生類的對(duì)象

//什么也不做,僅完成對(duì)象obj的構(gòu)造與析構(gòu) return0;}§7.3繼承與構(gòu)造函數(shù)、析構(gòu)函數(shù)運(yùn)行結(jié)果:Constructingbaseobject.ConstructingCobject.Constructingderivedobject.Destructingderivedobject.DestructingCobject.Destructingbaseobject.317.3.1構(gòu)造函數(shù)與析構(gòu)函數(shù)的調(diào)用次序§7.3繼承與構(gòu)造7.3.2向基類構(gòu)造函數(shù)傳遞實(shí)際參數(shù)給基類構(gòu)造函數(shù)傳遞實(shí)際參數(shù)是通過向派生類構(gòu)造函數(shù)傳遞實(shí)際參數(shù)以及初始化列表來間接實(shí)現(xiàn)傳遞的。

帶初始化列表的派生類構(gòu)造函數(shù)的一般形式

派生類名(參數(shù)表):基類名(調(diào)用基類構(gòu)造函數(shù)參數(shù)表){ 派生類構(gòu)造函數(shù)體}

§7.3繼承與構(gòu)造函數(shù)、析構(gòu)函數(shù)327.3.2向基類構(gòu)造函數(shù)傳遞實(shí)際參數(shù)§7.3繼承與構(gòu)造函7.3.2向基類構(gòu)造函數(shù)傳遞實(shí)際參數(shù)#include<iostream.h>classBase{ intprivate1,private2; public: Base(intp1,intp2) {private1=p1;private2=p2;} intinc1(){return++private1;} intinc2(){return++private2;} voiddisplay(){cout<<"private1="<<private1 <<",privte2="<<private2<<"\n";}};§7.3繼承與構(gòu)造函數(shù)、析構(gòu)函數(shù)337.3.2向基類構(gòu)造函數(shù)傳遞實(shí)際參數(shù)§7.3繼承與構(gòu)造函7.3.2向基類構(gòu)造函數(shù)傳遞實(shí)際參數(shù)classDerived:privateBase{ intprivate3; Baseprivate4; public: Derived(intp1,intp2,intp3,intp4,intp5):Base(p1,p2),private4(p3,p4) {private3=p5;} intinc1(){returnBase::inc1();} intinc3(){return++private3;}voiddisplay(){ Base::display(); private4.display(); cout<<"private3="<<private3<<"\n"; }}; §7.3繼承與構(gòu)造函數(shù)、析構(gòu)函數(shù)347.3.2向基類構(gòu)造函數(shù)傳遞實(shí)際參數(shù)§7.3繼承與構(gòu)造函7.3.2向基類構(gòu)造函數(shù)傳遞實(shí)際參數(shù)

voidmain(){ Derivedobj(17,18,1,2,-5); obj.inc1(); obj.display();}輸出結(jié)果:private1=18,private2=18private1=1,private2=2private3=-5obj1718-512private1 從基類繼承private2private3private4.private1private4.private218§7.3繼承與構(gòu)造函數(shù)、析構(gòu)函數(shù)357.3.2向基類構(gòu)造函數(shù)傳遞實(shí)際參數(shù) obj17priva7.4.1恢復(fù)訪問控制方式使用訪問聲明將一些被屏蔽的共有成員恢復(fù)到原來的訪問控制狀態(tài)。訪問聲明采用作用域運(yùn)算符”::”,它的一般形式是:基類名::成員名/程序:ACCESS.CPP//功能:演示在派生類中如何調(diào)整從基類繼承下來的成員的訪問控制方式#include<iostream.h>classBase{public: voidset_i(intx) { i=x; } intget_i() { returni; }protected: inti;};§7.4繼承成員的調(diào)整367.4.1恢復(fù)訪問控制方式§7.4繼承成員的調(diào)整367.4.1恢復(fù)訪問控制方式classDerived:privateBase{public: Base::set_i;//訪問聲明 voidset_j(intx) { j=x; } intget_ij() { returni+j; }protected: intj;};intmain(){ Derivedobj; obj.set_i(5);//set_i()已從私有轉(zhuǎn)為公有 obj.set_j(7);//set_j()本來就是公有 cout<<obj.get_ij()<<endl;//get_ij()本來就是公有 return0;}§7.4繼承成員的調(diào)整377.4.1恢復(fù)訪問控制方式§7.4繼承成員的調(diào)整377.4.2繼承成員的重定義函數(shù)重載:派生類中增加了一個(gè)與基類成員函數(shù)同名的成員函數(shù),但函數(shù)的形式參數(shù)個(gè)數(shù)、類型或次序不同,編譯程序認(rèn)為是增加了一個(gè)新的成員函數(shù)。重定義:派生類中定義了一個(gè)函數(shù)原型與繼承成員函數(shù)一樣的成員函數(shù),但語義上修改了成員函數(shù)的實(shí)現(xiàn)。對(duì)成員函數(shù)重定義后,派生類對(duì)象使用函數(shù)名進(jìn)行函數(shù)調(diào)用,那么使用的是派生類中新定義的成員函數(shù)。此時(shí)稱這個(gè)派生類中的成員的名字支配了基類的名字。繼承成員被重定義后,若想繼續(xù)使用基類被屏蔽了的成員,可用:

基類名::成員名來使用?!?.4繼承成員的調(diào)整387.4.2繼承成員的重定義§7.4繼承成員的調(diào)整387.4.2繼承成員的重定義//程序:ACCESS1.CPP//功能:演示在派生類繼承成員重定義#include<iostream.h>classBase{public: voidset_i(intx) { i=x; } intget_i() { returni; } voidprint() { cout<<"i="<<i<<endl; }protected: inti;};§7.4繼承成員的調(diào)整397.4.2繼承成員的重定義§7.4繼承成員的調(diào)整397.4.2繼承成員的重定義classDerived:privateBase{public: Base::set_i;//訪問聲明 voidset_j(intx) { j=x; } intget_ij() { returni+j; }

voidprint() { Base::print();//調(diào)用基類被屏蔽的成員函數(shù) cout<<"j="<<j<<endl; }protected: intj;};§7.4繼承成員的調(diào)整407.4.2繼承成員的重定義§7.4繼承成員的調(diào)整407.4.2繼承成員的重定義intmain(){ Derivedobj; obj.set_i(5);//set_i()已從私有轉(zhuǎn)為公有 obj.set_j(7);//set_j()本來就是公有 obj.print(); cout<<obj.get_ij()<<endl; return0;}程序運(yùn)行結(jié)果i=5J=712§7.4繼承成員的調(diào)整417.4.2繼承成員的重定義§7.4繼承成員的調(diào)整417.4.3繼承成員的重命名重命名:在派生類中不改變繼承成員的語義,僅僅為成員起一個(gè)新的名字。目的:解決名字沖突問題(在多繼承情況下);允許派生類根據(jù)新的應(yīng)用環(huán)境選擇更適合的術(shù)語來命名,使得繼承成員的名字更容易理解。C++沒有提供直接的重命名機(jī)制?!?.4繼承成員的調(diào)整427.4.3繼承成員的重命名§7.4繼承成員的調(diào)整427.4.3繼承成員的重命名classCSquare:publicCRectangle//正方形類,派生自矩形類{public:CSquare(intnX,intnY,intnEdge);intGet_Square_Area();//重命名計(jì)算面積成員函數(shù)intGetEdge();//返回邊長(zhǎng)};

IntCSquare::Get_Square_Area(){returnCRectangle::GetArea();}§7.4繼承成員的調(diào)整GetArea();437.4.3繼承成員的重命名§7.4繼承成員的調(diào)整GetA7.4.4屏蔽繼承成員

屏蔽繼承成員:實(shí)現(xiàn)在派生類中不能再訪問從基類繼承過來的某些成員。方法:通過訪問控制方式protected和private//程序:PROHIBIT.CPP//功能:演示在派生類中如何屏蔽從基類繼承下來的公有成員#include<iostream.h>classBase{public: voidset_i(intx) { i=x; } intget_i() { returni; }protected: inti;};§7.4繼承成員的調(diào)整447.4.4屏蔽繼承成員§7.4繼承成員的調(diào)整447.4.4屏蔽繼承成員classDerived:publicBase{public: voidset_ij(intx,inty) { i=x; j=y; } intget_ij() { returni+j; }protected: intj;private: voidset_i(intx){}};§7.4繼承成員的調(diào)整private457.4.4屏蔽繼承成員§7.4繼承成員的調(diào)整privat7.4.4屏蔽繼承成員intmain(){ Derivedobj; //obj.set_i(5);//不可訪問錯(cuò)誤,除非使用obj.BASE::set_i(8) obj.set_ij(5,7);//set_ij()本來就是公有 cout<<obj.get_ij()<<endl; return0;}§7.4繼承成員的調(diào)整obj.Base::set_i(8);如果連obj.Base::set_i(8);這種形式都不讓用,怎么辦?467.4.4屏蔽繼承成員§7.4繼承成員的調(diào)整obj.Ba§7.5多重繼承7.5.1多重繼承的應(yīng)用背景

多重繼承:一個(gè)類由多個(gè)基類派生而來

單繼承:一個(gè)類由單個(gè)基類派生而來父親基因母親基因兒女基因博士教師在職博士istreamostreamiostream47§7.5多重繼承7.5.1多重繼承的應(yīng)用背景父親基因母親§7.5多重繼承7.5.2多重繼承的語法形式class派生類名:access基類名1,……,access基類名n{ …};

基類名2基類名1基類名n派生類名……48§7.5多重繼承7.5.2多重繼承的語法形式基類名2基類§7.5多重繼承7.5.2多重繼承的語法形式//程序:MULINHER.CPP//功能:演示多重繼承的作用#include<iostream.h>classBase1{public: voidshow_i() { cout<<"i="<<i<<endl; }protected: inti;};49§7.5多重繼承7.5.2多重繼承的語法形式49§7.5多重繼承7.5.2多重繼承的語法形式classBase2{public: voidshow_j() { cout<<"j="<<j<<endl; }protected: intj;};classDerived:publicBase1,publicBase2{public: voidset(intx,inty) { i=x; j=y; }};50§7.5多重繼承7.5.2多重繼承的語法形式50§7.5多重繼承7.5.2多重繼承的語法形式intmain(){ Derivedobj; obj.set(5,7); obj.show_i();//從Base1繼承下來 obj.show_j();//從Base2繼承下來 return0;}51§7.5多重繼承7.5.2多重繼承的語法形式517.5.3多重繼承的名字沖突問題名字沖突:指兩個(gè)基類具有相同名字的成員時(shí),在派生類中這個(gè)名字會(huì)產(chǎn)生二義性,即編譯程序無法確定派生類的對(duì)象使用該名字時(shí)應(yīng)調(diào)用哪一基類中的版本。例:classBASE1{public: voidshow(){cout<<i<<"\n";}protected: inti;};

classBASE2{public: voidshow(){ cout<<j<<"\n";}protected: intj;};§7.5多重繼承527.5.3多重繼承的名字沖突問題§7.5多重繼承527.5.3多重繼承的名字沖突問題//多重繼承引起名字沖突:DERIVED的兩個(gè)基類BASE1和BASE2有相同的名字show()。classDERIVED:publicBASE1,publicBASE2{ public: voidset(intx,inty) {i=x; j=y; }}; //派生類在編譯時(shí)不出錯(cuò):C++并不禁止名字沖突的產(chǎn)生

intmain(){ DERIVEDobj; //聲明一個(gè)派生類的對(duì)象

obj.set(5,7); //set()是DERIVED類自身定義的 //obj.show();//二義性錯(cuò)誤,編譯程序無法決定調(diào)用哪一個(gè)版本 obj.BASE1::show(); //顯式地調(diào)用從BASE1繼承下來show() obj.BASE2::show(); //顯式地調(diào)用從BASE2繼承下來show() return0;}§7.5多重繼承537.5.3多重繼承的名字沖突問題§7.5多重繼承537.5.3多重繼承的名字沖突問題名字沖突的解決方法使用時(shí),用作用域運(yùn)算符明確指明使用那個(gè)基類的成員函數(shù)

obj.BASE1::show();在派生類中重定義有名字沖突的成員classDERIVED:publicBASE1,publicBASE2{public: voidset(intx,inty){i=x;j=y; }

voidshow() { cout<<i<<"\n";cout<<j<<"\n"; }};

intmain(){ DERIVEDobj; //聲明一個(gè)派生類的對(duì)象

obj.set(5,7); //set()是DERIVED類自身定義的

obj.show();//無二義性問題,調(diào)用的是DERIVED中新定義的版本 obj.BASE1::show(); //仍然可調(diào)用從BASE1繼承下來show() obj.BASE2::show(); //仍然可調(diào)用從BASE2繼承下來show() return0;}§7.5多重繼承547.5.3多重繼承的名字沖突問題§7.5多重繼承547.5.4多重繼承的構(gòu)造函數(shù)和析構(gòu)函數(shù)多個(gè)基類構(gòu)造函數(shù)的調(diào)用次序是按基類在被繼承時(shí)所聲明的次序、從左到右依次調(diào)用的,與它們?cè)谂缮悩?gòu)造函數(shù)實(shí)現(xiàn)中的初始化列表中出現(xiàn)的次序無關(guān)。例:classDERIVED:publicBASE2,publicBASE1{ public: DERIVED(intx,inty):BASE1(x),BASE2(y) { cout<<"Constructingderivedobject.\n"; } ……};……DERIVEDobj(3,4);則obj在創(chuàng)建時(shí),先調(diào)用BASE2的構(gòu)造函數(shù),然后調(diào)用BASE1的構(gòu)造函數(shù),最后才執(zhí)行自己DERIVED的構(gòu)造函數(shù)§7.5多重繼承557.5.4多重繼承的構(gòu)造函數(shù)和析構(gòu)函數(shù)§7.5多重繼承57.5.4多重繼承的構(gòu)造函數(shù)和析構(gòu)函數(shù)#include<iostream.h>classBase1{public: Base1(intx) {cout<<x<<"->Constructingbase1object.\n";} ~Base1() {cout<<"Destructingbase1object.\n";}};classBase2{public: Base2(intx) {cout<<x<<"->Constructingbase2object.\n";} ~Base2() {cout<<"Destructingbase2object.\n";}};§7.5多重繼承567.5.4多重繼承的構(gòu)造函數(shù)和析構(gòu)函數(shù)§7.5多重繼承57.5.4多重繼承的構(gòu)造函數(shù)和析構(gòu)函數(shù)classDerived:publicBase2,publicBase1{public: Derived(intx,inty):Base1(x),Base2(y) {cout<<"Constructingderivedobject.\n";} ~Derived() {cout<<"Destructingderivedobject.\n";}};intmain(){ Derivedobj(10,20);

return0;}§7.5多重繼承運(yùn)行結(jié)果:20->Constructingbase2object.10->Constructingbase1object.Constructingderivedobject.Destructingderivedobject.Destructingbase1object.Destructingbase2object.577.5.4多重繼承的構(gòu)造函數(shù)和析構(gòu)函數(shù)§7.5多重繼承運(yùn)§7.6重復(fù)繼承7.6.1重復(fù)繼承的應(yīng)用背景1.定義定義:指一個(gè)派生類多次繼承同一個(gè)基類C++中關(guān)于繼承的限制不允許直接或間接讓一個(gè)類繼承自己不允許一個(gè)派生類直接繼承同一個(gè)基類兩次以上不允許一個(gè)基類即是直接基類又是間接基類BBDBB1DB58§7.6重復(fù)繼承7.6.1重復(fù)繼承的應(yīng)用背景BBDBB7.6.1重復(fù)繼承的應(yīng)用背景2.重復(fù)繼承的兩種類型復(fù)制繼承:被多次重復(fù)繼承的基類有多個(gè)實(shí)體副本 共享繼承:被多次重復(fù)繼承的基類只有一個(gè)實(shí)體副本

§7.6重復(fù)繼承BB1B2Diosistreamostreamiostream597.6.1重復(fù)繼承的應(yīng)用背景§7.6重復(fù)繼承BB1B27.6.1重復(fù)繼承的應(yīng)用背景例:復(fù)制繼承:department

共享繼承:name,sex

§7.6重復(fù)繼承nameSexdeparmentSTUDENTTEACHERIN_SERVICEPERSON607.6.1重復(fù)繼承的應(yīng)用背景§7.6重復(fù)繼承name7.6.2重復(fù)繼承的二義性問題若在繼承時(shí)沒有作特殊聲明,此時(shí)采用的是復(fù)制繼承,會(huì)導(dǎo)致重復(fù)繼承的二義性問題。例:classBase{public: inti;};

classBase1:publicBase{ public: intj;};

classBase2:publicBase{ public: intk;};

§7.6重復(fù)繼承BASEBASE1BASE2DERIVED617.6.2重復(fù)繼承的二義性問題§7.6重復(fù)繼承BASE7.6.2重復(fù)繼承的二義性問題classDERIVED:publicBase1,publicBase2{ public: intsum;};

voidmain(){ DERIVEDobj; //聲明一個(gè)派生類對(duì)象

//obj.i=3; //錯(cuò)誤,編譯程序無法確定使用i的哪一份副本 obj.j=5; //正確的,使用從Base1繼承下來的j obj.k=7; //正確的,使用從Base2繼承下來的k}objBase1.Base.iBase1.jBase2.Base.iBase.ksum函數(shù)指針§7.6重復(fù)繼承627.6.2重復(fù)繼承的二義性問題objBase1.Bas7.6.2重復(fù)繼承的二義性問題解決二義性的方法如不改變重復(fù)繼承的方法(還是復(fù)制繼承),則采用作用域運(yùn)算符::明確指明采用哪個(gè)副本intmain(){ Derivedobj; obj.Base1::i=3; obj.Base2::i=5; obj.j=7; obj.k=9;cout<<obj.Base1::i+obj.j+obj.k<<endl; cout<<obj.Base2::i+obj.j+obj.k<<endl; return0;}改用共享方式繼承:用虛基類機(jī)制保證任何派生類中只提供一個(gè)基類的副本§7.6重復(fù)繼承637.6.2重復(fù)繼承的二義性問題§7.6重復(fù)繼承637.6.3虛基類定義:虛基類是當(dāng)基類被繼承時(shí),在基類的繼承訪問控制關(guān)鍵字前面加上關(guān)鍵字virtual來定義的。普通基類與虛基類之間的唯一區(qū)別只有在派生類重復(fù)繼承了某一基類時(shí)才表現(xiàn)出來,虛基類用于實(shí)現(xiàn)共享繼承?!?.6重復(fù)繼承647.6.3虛基類§7.6重復(fù)繼承647.6.3虛基類#include<iostream.h>classBase{public: inti;};classBase1:virtualpublicBase{public: intj; };classBase2:virtualpublicBase{public: intk; };classDerived:publicBase1,publicBase2{public: intsum;};§7.6重復(fù)繼承657.6.3虛基類§7.6重復(fù)繼承657.6.3虛基類intmain(){ DERIVEDobj; //聲明一個(gè)派生類對(duì)象

obj.i=3; //正確cout<<"obj.i="<<obj.i<<endl; obj.j=7; obj.k=9; cout<<"obj.j="<<obj.j<<endl;cout<<"obj.k="<<obj.k<<endl; obj.sum=obj.i+obj.j+obj.k; cout<<"obj.sum="<<obj.sum<<endl; return0;}

objiBase1.jBase2.ksum函數(shù)指針§7.6重復(fù)繼承obj.Base1::i=3;?存在的問題:(1)在設(shè)計(jì)Base、Base1、Base2時(shí)并不知道Derived是需要以共享或復(fù)制繼承。(2)若有大于一個(gè)類重復(fù)繼承Base,但有的需要共享繼承,有的需要復(fù)制繼承667.6.3虛基類obji§7.6重復(fù)繼承obj.B7.6.4虛基類的構(gòu)造函數(shù)與析構(gòu)函數(shù)對(duì)虛基類構(gòu)造函數(shù)的調(diào)用總是先于普通基類的構(gòu)造函數(shù)。

虛基類的唯一副本只被初始化一次C++中構(gòu)造函數(shù)的調(diào)用次序(1)最先調(diào)用虛基類的構(gòu)造函數(shù)。(2)其次調(diào)用普通基類的構(gòu)造函數(shù),多個(gè)基類則按派生類聲明時(shí)列出的次序、從左到右調(diào)用,而不是初始化列表中的次序。(3)再次調(diào)用對(duì)象成員的構(gòu)造函數(shù),按類聲明中對(duì)象成員出現(xiàn)的次序調(diào)用,而不是初始化列表中的次序。(4)最后執(zhí)行派生類的構(gòu)造函數(shù)?!?.6重復(fù)繼承677.6.4虛基類的構(gòu)造函數(shù)與析構(gòu)函數(shù)§7.6重復(fù)繼承67.6.4虛基類的構(gòu)造函數(shù)與析構(gòu)函數(shù)#include<iostream.h>classBaseA{public: BaseA() {cout<<"\nThisisBaseAConstructing.\n";} ~BaseA() {cout<<"\nThisisBaseADestructing.\n";}};classBaseB{public: BaseB() {cout<<"\nThisisBaseBConstructing.\n";} ~BaseB() {cout<<"\nThisisBaseBDestructing.\n";}};§7.6重復(fù)繼承687.6.4虛基類的構(gòu)造函數(shù)與析構(gòu)函數(shù)§7.6重復(fù)繼承67.6.4虛基類的構(gòu)造函數(shù)與析構(gòu)函數(shù)classDerivedA:publicBaseB,virtualpublicBaseA{public: DerivedA() {cout<<"\nThisisDerivedAConstructing.\n";}~DerivedA() {cout<<"\nThisisDerivedADestructing.\n";}};classDerivedB:publicBaseB,virtualpublicBaseA{public: DerivedB() {cout<<"\nThisisDerivedBConstructing.\n";}~DerivedB() {cout<<"\nThisisDerivedBDestructing.\n";}};§7.6重復(fù)繼承697.6.4虛基類的構(gòu)造函數(shù)與析構(gòu)函數(shù)§7.6重復(fù)繼承67.6.4虛基類的構(gòu)造函數(shù)與析構(gòu)函數(shù)classDerived:publicDerivedA,virtualpublicDerivedB{public: Derived() {cout<<"\nThisisDerivedConstructing.\n";}~Derived() {cout<<"\nThisisDerivedDestructing.\n";}};intmain(){ Derivedobj; return0;}§7.6重復(fù)繼承DerivedADerivedBDerivedBaseABaseB707.6.4虛基類的構(gòu)造函數(shù)與析構(gòu)函數(shù)§7.6重復(fù)繼承D7.6.4虛基類的構(gòu)造函數(shù)與析構(gòu)函數(shù)§7.6重復(fù)繼承DerivedADerivedBDerivedBaseABaseBvirtual運(yùn)行結(jié)果:ThisisBaseAConstructing.ThisisBaseBConstructing.ThisisDerivedBConstructing.ThisisBaseBConstructing.ThisisDerivedAConstructing.ThisisDerivedConstructing.ThisisDerivedDestructing.ThisisDerivedADestructing.ThisisBaseBDestructing.ThisisDerivedBDestructing.ThisisBaseBDestructing.ThisisBaseADestructing.virtual717.6.4虛基類的構(gòu)造函數(shù)與析構(gòu)函數(shù)§7.6重復(fù)繼承D7.7.1問題的提出小型公司人員信息管理某小型公司,主要有四類人員:經(jīng)理、技術(shù)人員、銷售經(jīng)理和推銷員。要求存儲(chǔ)這些人員的姓名、編號(hào)、級(jí)別、當(dāng)月薪水,計(jì)算月薪總額并顯示全部信息。人員編號(hào)基數(shù)為1000,每輸入一個(gè)人員的信息,編號(hào)順序加1。程序要對(duì)所有人員有提升級(jí)別的功能。為簡(jiǎn)單起見,所有人員的初始級(jí)別均為1級(jí),然后進(jìn)行升級(jí),經(jīng)理升為4級(jí),技術(shù)人員和銷售經(jīng)理升為3級(jí),推銷員仍為1級(jí)。月薪計(jì)算辦法是:經(jīng)理拿固定月薪8000元;技術(shù)人員按每小時(shí)100元領(lǐng)取月薪;推銷員的月薪按該推銷員當(dāng)月銷售額的4%提成;銷售經(jīng)理既拿固定月薪也領(lǐng)取銷售提成,固定月薪為5000元,銷售提成為所管轄部門當(dāng)月銷售總額的5‰?!?.7多繼承的實(shí)例727.7.1問題的提出§7.7多繼承的實(shí)例727.7.2設(shè)計(jì)

根據(jù)上述需求,設(shè)計(jì)一個(gè)基類employee,然后派生出technician(技術(shù)人員)類、manager(經(jīng)理)類和salesman(推銷員)類。由于銷售經(jīng)理(salesmanager)既是經(jīng)理又是銷售人員,兼具兩類人員的特點(diǎn),因此同時(shí)繼承manager和salesman兩個(gè)類。在基類中,除了定義構(gòu)造函數(shù)和析構(gòu)函數(shù)以外,還應(yīng)統(tǒng)一定義對(duì)各類人員信息都應(yīng)有的操作,這樣可以規(guī)范各派生類的基本行為。但是各類人員的月薪計(jì)算方法不同,不能在基類employee中統(tǒng)一定義計(jì)算方法。各類人員信息的顯示內(nèi)容也不同,同樣不能在基類中統(tǒng)一定義顯示方法。因此,在employee類中用純虛函數(shù)的方式定義了計(jì)算月薪函數(shù)pay()和顯示信息函數(shù)displayStatus(),然后在派生類中再根據(jù)各自的同名函數(shù)實(shí)現(xiàn)具體的功能。由于salesmanager的兩個(gè)基類又有公共基類employee,為避免二義性,這里將employee類設(shè)計(jì)為虛基類?!?.7多繼承的實(shí)例737.7.2設(shè)計(jì)§7.7多繼承的實(shí)例737.7.2設(shè)計(jì)

§7.7多繼承的實(shí)例char*name;intindividualEmpNo;intgrade;floataccumPay;staticintemployeeNo;voidpay();voidpromote(int);voiddisplayStatus();employeefloathourlyRate;intworkHours;

voidpay();voiddisplayStatus();technicianfloatmonthlyPay;

voidpay();voiddisplayStatus();managerfloatCommrate;floatsales;voidpay();voiddisplayStatus();salesman

voidpay();voiddisplayStatus();salesmanager747.7.2設(shè)計(jì)§7.7多繼承的實(shí)例c7.7.3編程//employee.hclassemployee{protected:char*name;//姓名intindividualEmpNo;//個(gè)人編號(hào)intgrade;//級(jí)別floataccumPay;//月薪總額staticintemployeeNo;//本公司職員編號(hào)目前最大值public:employee();~employee();voidpay();//計(jì)算月薪函數(shù)voidpromote(int);//升級(jí)函數(shù)voiddisplayStatus();//顯示人員信息};§7.7多繼承的實(shí)例757.7.3編程§7.7多繼承的實(shí)例757.7.3編程classtechnician:publicemployee//技術(shù)人員{private:floathourlyRate;//每小時(shí)酬金intworkHours;//每月工作時(shí)數(shù)public:technician();voidpay();//計(jì)算月薪函數(shù)voiddisplayStatus();//顯示人員信息};classmanager:virtualpublicemployee//經(jīng)理{protected:floatmonthlyPay;//固定月薪數(shù)public:manager();voidpay();//計(jì)算月薪函數(shù)voiddisplayStatus();//顯示人員信息};§7.7多繼承的實(shí)例767.7.3編程§7.7多繼承的實(shí)例767.7.3編程classsalesman:virtualpublicemployee//推銷員{protected:floatCommRate;//按銷售額提取酬金的百分比floatsales;//當(dāng)月銷售額public:salesman();voidpay();//計(jì)算月薪函數(shù)voiddisplayStatus();//顯示人員信息};classsalesmanager:publicmanager,publicsalesman{public:salesmanager();voidpay();//計(jì)算月薪函數(shù)voiddisplayStatus();//顯示人員信息};§7.7多繼承的實(shí)例777.7.3編程§7.7多繼承的實(shí)例777.7.3編程//empfunc.cpp#include<iostream.h>#include<string.h>#include<conio.h>#include"employee.h"intemployee::employeeNo=1000;//職工編號(hào)基數(shù)為1000employee::employee(){charstr[30];cout<<"pleaseinputemployee'sname:";//輸入員工姓名cin>>str;name=newchar[strlen(str)+1];strcpy(name,str);individualEmpNo=++employeeNo;//新輸入員工,其編號(hào)為目前最大編號(hào)加1grade=1;//級(jí)別初值為1accumPay=0;//月薪總額初值為0}§7.7多繼承的實(shí)例787.7.3編程§7.7多繼承的實(shí)例787.7.3編程employee::~employee(){delete[]name;//構(gòu)造函數(shù)中動(dòng)態(tài)分配了內(nèi)存}voidemployee::pay()//計(jì)算月薪,空函數(shù){}voidemployee::promote(intincre){grade+=incre;//升級(jí),提升的級(jí)數(shù)由incre指定}voidemployee::displayStatus()//顯示人員信息,空函數(shù){}§7.7多繼承的實(shí)例797.7.3編程§7.7多繼承的實(shí)例797.7.3編程technician::technician(){hourlyRate=100;//每小時(shí)酬金100元}voidtechnician::pay(){cout<<"input"<<name<<"theworkHoursofthismonth:";//輸入本月的工作時(shí)數(shù)cin>>workHours;accumPay=hourlyRate*workHours;//計(jì)算月薪,按小時(shí)計(jì)酬cout<<"Technician:"<<name<<"No:"<<individualEmpNo<<"monthsalary:"<<accumPay<<endl;}voidtechnician::displayStatus(){cout<<"Technician:"<<name<<"No:"<<individualEmpNo<<"grade:"<<grade<<"thismonthsalary:"<<accumPay<<endl;}§7.7多繼承的實(shí)例807.7.3編程§7.7多繼承的實(shí)例807.7.3編程manager::manager(){monthlyPay=8000;//固定月薪8000}voidmanager::pay(){accum

溫馨提示

  • 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)論