C++程序設(shè)計(jì)基礎(chǔ)教程 第2版 課件 第11章 繼承與派生_第1頁(yè)
C++程序設(shè)計(jì)基礎(chǔ)教程 第2版 課件 第11章 繼承與派生_第2頁(yè)
C++程序設(shè)計(jì)基礎(chǔ)教程 第2版 課件 第11章 繼承與派生_第3頁(yè)
C++程序設(shè)計(jì)基礎(chǔ)教程 第2版 課件 第11章 繼承與派生_第4頁(yè)
C++程序設(shè)計(jì)基礎(chǔ)教程 第2版 課件 第11章 繼承與派生_第5頁(yè)
已閱讀5頁(yè),還剩74頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

第11章繼承與派生主要內(nèi)容11.1類的繼承與派生11.2派的繼承方式11.3派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)11.4多重繼承11.5應(yīng)用實(shí)例11.1類的繼承與派生類的繼承:新類從已有類(父類)那里獲得其已有特性。類的派生:已有類(父類)產(chǎn)生新的子類。派生類繼承了基類的所有數(shù)據(jù)成員和成員函數(shù),并可對(duì)成員作必要的增加或調(diào)整?;惡团缮愊鄬?duì)而言:一個(gè)基類可派生出多個(gè)派生類,每個(gè)派生類又可作為基類再派生出新的派生類。11.1.1繼承與派生的實(shí)例設(shè)計(jì)的原則:公共的特性抽象封裝成基類,獨(dú)有的特性在派生類里實(shí)現(xiàn)。11.1.1繼承與派生的實(shí)例學(xué)校人員管理:學(xué)生教師管理人員教師管理人員人員(姓名,性別,年齡,學(xué)院)(學(xué)號(hào),姓名,性別,年齡,學(xué)院,專業(yè),班級(jí))(工號(hào),姓名,性別,年齡,學(xué)院,職稱)(工號(hào),姓名,性別,年齡,學(xué)院,科室,職務(wù))(工號(hào),姓名,性別,年齡,學(xué)院,職稱,科室,職務(wù))人類教師類學(xué)生類管理人員類教師管理人員類多繼承:派生類有多個(gè)基類單繼承:派生類只有一個(gè)基類直接基類間接基類11.1.1繼承與派生的實(shí)例單繼承(singleinheritance):一個(gè)派生類只從一個(gè)基類派生。多重繼承(multipleinheritance):一個(gè)派生類有兩個(gè)或兩個(gè)以上基類。11.1.2派生類的定義聲明派生類的一般形式class派生類名:[繼承方式]基類名{派生類新增的成員};繼承方式:public,private和protected。默認(rèn)繼承方式:private?;悾喝藛T類classPerson //定義Person類{ public:

Person(constchar*Name,intAge,charSex);

char*GetName(); intGetAge();

charGetSex();voidDisplay();private: charname[50]; charsex; intage;};classStudent:publicPerson//公有繼承{public:

Student(char*pName,intAge,charSex,char*pId,floatscore):Person(pName,Age,Sex);

//派生類新增的成員函數(shù) char*GetId();

floatGetScore();

voidDisplay(); private:

//派生類新增的數(shù)據(jù)成員charsid[9]; floatscore;};派生類:學(xué)生類派生類:教師類classTeacher:publicPerson{//公有繼承public:

Teacher(char*pName,intAge,charSex,char*pId,char*pprof,floatSalary):Person(pName,Age,Sex);

char*GetId();

char*GetProf();

floatGetSalary();

voidDisplay();private: charid[9];charprof[12]; floatsalary;};11.1.3派生類的生成過程(1)繼承基類成員(2)改造基類成員(3)增加新的成員11.2類的繼承方式公用繼承私有繼承保護(hù)繼承繼承方式影響基類成員在派生類的訪問屬性(1)公用繼承(publicinheritance)基類的公用和保護(hù)成員在派生類中保持原有訪問屬性,私有成員仍為基類私有。(2)私有繼承(privateinheritance)基類的公用和保護(hù)成員在派生類中成了私有成員,私有成員仍為基類私有。(3)受保護(hù)的繼承(protectedinheritance)基類的公用和保護(hù)成員在派生類中成了保護(hù)成員,私有成員仍為基類私有。11.2.1公用繼承公有繼承時(shí),基類的公有成員和保護(hù)成員作為派生類的成員時(shí),都保持原有狀態(tài),而私有成員仍是私有。公有繼承時(shí),派生類的對(duì)象只可訪問基類中的公有成員,不能訪問其它成員。派生類的成員函數(shù)可以訪問基類中的公有成員和保護(hù)成員,不可訪問其私有成員。11.2.1公用繼承classstudent{private:intage;protected:charsex;public:intGetage(){returnage;}};classgraduatestudent:publicstudent{private:intstunum;

public:voiddisplay();};即:student::Getage()//

//不可訪問基類的私有成員//派生類的私有成員//基類的公有成員公有繼承voidgraduatestudent::display()//派生類成員函數(shù)定義{cout<<"age:"<<age<<endl;cout<<"stunum:"<<stunum<<endl;cout<<"age:"<<Getage()<<endl;cout<<"sex:"<<sex<<endl;//即:student::sex基類的保護(hù)成員}voidmain(){graduatestudentzh;//生成派生類對(duì)象

cout<<zh.Getage();//即:student::Getage();基類中的公有成員

zh.display();//訪問派生類中的公有成員

cout<<zh.sex;cout<<zh.stunum;cout<<zh.age;}//

//

error,訪問基類中保護(hù)成員//

//

error,訪問派生類中私有成員//

//

error,訪問基類中私有成員公有繼承11.2.2私有繼承私有繼承時(shí),基類的公有成員和保護(hù)成員都作為派生類的私有成員,并且不能被這個(gè)派生類的子類所訪問。私有繼承時(shí),基類的成員只能由直接派生類訪問,而無法再往下繼承。私有繼承classstudent{private:intage;protected:charsex;public:intGetage(){returnage;}};classgraduatestudent:privatestudent{private:intstunum;public:voiddisplay();};私有繼承voidgraduatestudent::display()//派生類成員函數(shù)定義{

//cout<<"age:"<<age<<endl;//不可訪問基類的私有成員

cout<<"stunum:"<<stunum<<endl;//派生類的私有成員

cout<<"age:"<<Getage()<<endl;//基類的公有成員

cout<<"sex:"<<sex<<endl;

//即:student::sex基類的保護(hù)成員

}私有繼承voidmain(){graduatestudentzh;//生成派生類對(duì)象

//zh.Getage();//error,不能訪問私有成員zh.display();//訪問派生類中的公有成員//cout<<zh.sex;//error,不能訪問私有成員

//cout<<zh.stunum;//error,不能訪問私有成員

//cout<<zh.age;//error,不能訪問私有成員}11.2.3保護(hù)繼承保護(hù)繼承時(shí),基類的所有公有成員和保護(hù)成員都作為派生類的保護(hù)成員,并且只能被它的派生類成員函數(shù)或友元訪問,基類的私有成員仍是私有的。保護(hù)繼承時(shí),派生類的成員函數(shù)可以直接訪問從基類繼承而來的成員,但在類外不能直接訪問。保護(hù)繼承classstudent{private:intage;protected:charsex;public:intGetage(){returnage;}};classgraduatestudent:protectedstudent{private:intstunum;public:voiddisplay();};保護(hù)繼承voidgraduatestudent::display()//派生類成員函數(shù)定義{//cout<<"age:"<<age<<endl;//不可訪問基類的私有成員cout<<"stunum:"<<stunum<<endl;//派生類的私有成員cout<<"age:"<<Getage()<<endl;//基類的公有成員cout<<"sex:"<<sex<<endl;//即:student::sex

基類的保護(hù)成員

}保護(hù)繼承voidmain(){graduatestudentzh;//生成派生類對(duì)象

//zh.Getage();//error,不能訪問保護(hù)成員zh.Getnum();//訪問派生類中的公有成員//cout<<zh.sex;//

error,不能訪問保護(hù)成員

//cout<<zh.stunum;//error,不能訪問私有成員

//cout<<zh.age;//

error,不能訪問保護(hù)成員}11.2類的繼承方式派生類成員派生類中派生類外部下層派生類公用成員可以可以可以保護(hù)成員可以不可以可以私有成員可以不可以不可以不可訪問成員不可以不可以不可以多級(jí)派生時(shí)的訪問屬性直接派生類、間接派生類直接基類、間接基類例多級(jí)派生的訪問屬性classA

//基類{public:inti;

protected:voidf2();intj;private:intk;};classB:public

A{public:voidf3();

protected:voidf4();

private:intm;};classC:protectedB{public:voidf5();private:intn;};例多級(jí)派生的訪問屬性各成員在不同類中的訪問屬性if2jkf3f4mf5n基類A公有保護(hù)保護(hù)私有公有派生類B公有保護(hù)保護(hù)不可訪問公有保護(hù)私有保護(hù)派生類C保護(hù)保護(hù)保護(hù)不可訪問保護(hù)保護(hù)不可訪問公有私有多級(jí)派生時(shí)的訪問屬性派生類都不能訪問基類的私有成員,私有成員只能被本類的成員函數(shù)訪問。都采用公有繼承的多級(jí)派生,則直到最后一級(jí)派生類都能訪問基類的公有和保護(hù)成員。都采用私有繼承方式,經(jīng)過若干次派生之后,基類的所有成員變成不可訪問。都采用保護(hù)繼承方式,在派生類外無法訪問派生類中的任何成員。公有繼承:最常用。11.3派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)派生類的構(gòu)造函數(shù)派生類的析構(gòu)函數(shù)

構(gòu)造函數(shù)不能被繼承,對(duì)派生類必須重新定義構(gòu)造函數(shù)。在聲明一個(gè)派生類對(duì)象時(shí),系統(tǒng)首先要通過派生類的構(gòu)造函數(shù)調(diào)用基類的構(gòu)造函數(shù),對(duì)基類成員初始化;然后對(duì)派生類中新增的成員初始化。派生類的對(duì)象的數(shù)據(jù)結(jié)構(gòu)是由基類中說明的數(shù)據(jù)成員和派生類中說明的數(shù)據(jù)成員共同構(gòu)成。將派生類的對(duì)象中由基類中說明的數(shù)據(jù)成員和操作所構(gòu)成的封裝體稱為基類子對(duì)象,它由基類中的構(gòu)造函數(shù)進(jìn)行初始化。11.3.1派生類的構(gòu)造函數(shù)派生類構(gòu)造函數(shù)初始化對(duì)象基類的數(shù)據(jù)成員派生類新增的數(shù)據(jù)成員思路:在執(zhí)行派生類的構(gòu)造函數(shù)時(shí),調(diào)用基類的構(gòu)造函數(shù)。形式:派生類構(gòu)造函數(shù)(參數(shù)):參數(shù)化列表{派生類新增成員的初始化語(yǔ)句}36派生類的構(gòu)造函數(shù)帶有子對(duì)象的派生類的構(gòu)造函數(shù)形式:派生類構(gòu)造函數(shù)(參數(shù)表):基類構(gòu)造函數(shù)(參數(shù)表),對(duì)象成員1的構(gòu)造函數(shù)(參數(shù)表)……,對(duì)象成員n的構(gòu)造函數(shù)(參數(shù)表){派生類新增成員的初始化語(yǔ)句}37【例11-4】構(gòu)造函數(shù)的調(diào)用順序舉例#include<iostream>usingnamespacestd;classBase{ inta; public: Base(intx):a(x){//基類的構(gòu)造函數(shù)

cout<<"constructBaseclass"<<a<<endl; }};38classsubBase:publicBase{private:

intb,c;//類subBase中新增的普通成員

constintd;

Basex,y;//類subBase中新增的對(duì)象成員public:

subBase(intt):y(t+2),x(t+1),d(t+3),Base(t){

b=t;

c=t;

cout<<"constructsubBaseclass"<<b<<""<<c<<""<<d<<endl; }};intmain(){ subBases1(9); return0;//建立subBase類對(duì)象s1}constructBaseclass9constructBaseclass10constructBaseclass11constructsubBaseclass9912派生類構(gòu)造函數(shù)的調(diào)用順序

首先調(diào)用基類的構(gòu)造函數(shù);

其次執(zhí)行參數(shù)化表中部分所列出的對(duì)象成員的構(gòu)造函數(shù);

最后執(zhí)行派生類構(gòu)造函數(shù)的函數(shù)體。即先祖先(基類),再客人(對(duì)象成員),后自己(派生類本身)。11.3.2派生類的析構(gòu)函數(shù)派生類不能繼承基類的析構(gòu)函數(shù)?;惖那謇砉ぷ魅杂苫愇鰳?gòu)函數(shù)負(fù)責(zé)。執(zhí)行派生類的析構(gòu)函數(shù)時(shí),系統(tǒng)自動(dòng)調(diào)用基類和子對(duì)象的析構(gòu)函數(shù)。調(diào)用順序:先執(zhí)行派生類的析構(gòu)函數(shù),然后調(diào)用子對(duì)象的析構(gòu)函數(shù),最后調(diào)用基類的析構(gòu)函數(shù)。42【例11-5】析構(gòu)函數(shù)的調(diào)用順序舉例。#include<iostream>usingnamespacestd;classBase{ inta; public: Base(intx):a(x){ //基類的構(gòu)造函數(shù)

cout<<"constructBaseclass:"<<a<<endl; } ~Base(){ //基類Base的析構(gòu)函數(shù)

cout<<"destructBase:"<<a<<endl; }};classsubBase:publicBase{private:

intb,c;

constintd;

Basex,y;public: subBase(intt):y(t+2),x(t+1),d(t+3),Base(t){

b=t;

c=t;

cout<<"constructsubBaseclass:"<<b<<""<<c<<""<<d<<endl; } ~subBase(){

cout<<"destructsubBase:"<<b<<""<<c<<""<<d<<endl; }};intmain(){ subBases1(9); return0;}constructBaseclass:9constructBaseclass:10constructBaseclass:11constructsubBaseclass:9912destructsubBase:9912destructBase:11destructBase:10destructBase:911.4多重繼承多重繼承概念多重繼承的二義性虛基類4611.4.1多重繼承概念多重繼承:允許一個(gè)派生類同時(shí)繼承多個(gè)基類。聲明多重繼承的方法class派生類名:繼承方式基類名1,繼承方式基類名2,...,繼承方式基類名n{定義派生類自己的成員};47多繼承的構(gòu)造函數(shù)一般格式為:<派生類名>(<總參數(shù)表>):

<基類名1>(<參數(shù)表1>),<基類名2>(<參數(shù)表2>),…<子對(duì)象名>(<參數(shù)表n+1>){<派生類構(gòu)造函數(shù)體>};它必須同時(shí)負(fù)責(zé)該派生類所有基類構(gòu)造函數(shù)的調(diào)用。同時(shí),派生類的參數(shù)個(gè)數(shù)必須包含完成所有基類初始化所需的參數(shù)個(gè)數(shù)。派生類構(gòu)造函數(shù)的調(diào)用順序是:先執(zhí)行所有基類的構(gòu)造函數(shù)再執(zhí)行子對(duì)象類的構(gòu)造函數(shù)(若有)再執(zhí)行派生類本身的構(gòu)造函數(shù)注意:同一層次的各基類構(gòu)造函數(shù)的執(zhí)行順序取決于定義派生類時(shí)所指定的各基類順序,與派生類構(gòu)造函數(shù)中所定義的成員初始化表的各項(xiàng)順序無關(guān)?!纠?1-6】多重繼承舉例。#include<iostream>usingnamespacestd;classCBase1{ protected: intb; public: CBase1(intx=0){

b=x; cout<<"ConstructCBase1!"<<b<<endl; } ~CBase1(){

cout<<"DestructCBase1!"<<b<<endl; }};classCBase2{protected:

intb;public:

CBase2(intx=0){

b=x;

cout<<"ConstructCBase2!"<<b<<endl;

}

~CBase2(){

cout<<"DestructCBase2!"<<b<<endl;

}};classCDerived:publicCBase1,privateCBase2{protected:

CBase1b1;

CBase2b2;

intd;public:

CDerived(intx,inty,intz):b1(y),CBase2(y),b2(z),CBase1(x){

d=z;

cout<<"ConstructCDerived!"<<d<<endl;

}

~CDerived(){

cout<<"DestructCDerived!"<<d<<endl;

}};intmain(){ CDerivedd1(1,2,3); return0;}ConstructCBase1!1ConstructCBase2!2ConstructCBase1!2ConstructCBase2!3ConstructCDerived!3DestructCDerived!3DestructCBase2!3DestructCBase1!2DestructCBase2!2DestructCBase1!111.4.2多重繼承的二義性多重繼承情況下的二義性問題可分為兩種情況(1)從不同基類繼承的同名成員,在引用時(shí)產(chǎn)生二義性。(2)當(dāng)?shù)蛯优缮悘牟煌穆窂缴隙啻卫^承同一個(gè)基類時(shí),也會(huì)產(chǎn)生二義性。(1)兩個(gè)基類有同名成員classA{public:inta;voiddisplay();};classB{public:inta;voiddisplay();};classC:publicA,publicB{public:intb;voidshow();};voidmain(){Cc1;c1.a=3;c1.display();}編譯后:errorC2385:'C::a'isambiguouserrorC2385:'C::display'isambiguous消除二義性有兩種方法1、使用相應(yīng)的類名來標(biāo)識(shí) c1.A::display();2、由派生類提供統(tǒng)一的接口 voidC::show() {

A::display();

B::display();

…… }(2)兩個(gè)基類和派生類三者都有同名成員。將C類聲明改為:classC:publicA,publicB{public:inta;voiddisplay();};voidmain(){Cc1;c1.a=3;c1.display();}會(huì)有問題么?規(guī)則:基類的同名成員在派生類中被屏蔽,成為“不可見”的,或者說,派生類新增加的同名成員覆蓋了基類中的同名成員。因此如果在定義派生類對(duì)象的模塊中通過對(duì)象名訪問同名的成員,則訪問的是派生類的成員。(3)如果C從類A和B派生,而它們又從同一個(gè)基類派生classN{public:inta;voiddisplay()

{cout<<"A::a="<<a<<endl;}};classA:publicN{public:inta1;};classB:publicN{public:inta2;};classC:publicA,publicB{public:inta3;voidshow(){cout<<"a3="<<a3<<endl;}};intmain(){Cc1;//定義C類對(duì)象c1……..}怎樣才能訪問類A中從基類N繼承下來的成員呢?inta3;顯然不能用c1.a=3;c1.display();或c1.N::a=3;c1.N::display();因?yàn)檫@樣依然無法區(qū)別是類A中從基類N繼承下來的成員,還是類B中從基類N繼承下來的成員。應(yīng)當(dāng)通過類N的直接派生類名來指出要訪問的是類N的哪一個(gè)派生類中的基類成員。如:c1.A::a=3;c1.A::display();11.4.3虛基類虛基類的作用:在繼承間接共同基類時(shí)只保留一份成員。聲明虛基類的一般形式注:不是在聲明基類時(shí)聲明,而是在聲明派生類時(shí),指定繼承方式時(shí)聲明。class派生類名:virtual

繼承方式基類名classA//聲明基類A{…};classB:virtualpublicA//聲明A是B的虛基類{…};classC:virtualpublicA//聲明A是C的虛基類{…};注:為保證虛基類在派生類中只繼承一次,應(yīng)把該基類的所有直接派生類聲明為虛基類。67【例11-9】利用虛基類避免產(chǎn)生二義性。classFurniture{

public: Furniture(){ cout<<"constructFurniture"<<endl; } voidSetPrice(doubled){ price=d; } doubleGetPrice(){ returnprice; } protected: doubleprice;};classBed:virtualpublicFurniture{

public: Bed(){ cout<<"constructBed"<<endl; } voidSleep(){ cout<<"Sleeping..."; }};classSofa:virtualpublicFurniture{

public: Sofa(){ cout<<"constructSofa"<<endl; } voidWatchTV(){ cout<<"WatchingTV.\n"; }};classSleeperSofa:publicBed,publicSofa{ public: SleeperSofa():Sofa(),Bed(){ cout<<"constructSleeperSofa"<<endl; } voidFoldOut(){ cout<<"Foldoutthesofa.\n"; } voidFunction(){ Sleep(); WatchTV(); }};intmain(){ SleeperSofass; ss.SetPrice(2000); cout<<"PriceofSleeperSofa:"<<ss.GetPrice()<<endl; cout<<"FunctionofSleeperSofa:"; ss.Function(); return0;}constructFurnitureconstructBedconstructSofaconstructSleeperSofaPriceofSleeperSofa:2000FunctionofSleeperSofa:Sleep

溫馨提示

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