面向?qū)ο蟪绦蛟O(shè)計(jì)繼承演示文稿_第1頁
面向?qū)ο蟪绦蛟O(shè)計(jì)繼承演示文稿_第2頁
面向?qū)ο蟪绦蛟O(shè)計(jì)繼承演示文稿_第3頁
面向?qū)ο蟪绦蛟O(shè)計(jì)繼承演示文稿_第4頁
面向?qū)ο蟪绦蛟O(shè)計(jì)繼承演示文稿_第5頁
已閱讀5頁,還剩81頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

面向?qū)ο蟪绦蛟O(shè)計(jì)繼承演示文稿當(dāng)前第1頁\共有86頁\編于星期五\16點(diǎn)面向?qū)ο蟪绦蛟O(shè)計(jì)繼承當(dāng)前第2頁\共有86頁\編于星期五\16點(diǎn)第4章繼承繼承使軟件復(fù)用變得簡(jiǎn)單、易行,可以通過繼承復(fù)用已有的程序資源,縮短軟件開發(fā)的周期。本章主要介紹繼承的方式,要注意在繼承方式下派生類與基類對(duì)象之間的關(guān)系,以及派生類構(gòu)造函數(shù)如何提供對(duì)基類的構(gòu)造。當(dāng)前第3頁\共有86頁\編于星期五\16點(diǎn)4.1繼承的概念1、繼承的概念當(dāng)前第4頁\共有86頁\編于星期五\16點(diǎn)以存在的類為基礎(chǔ)定義新的類,新類即捅有基類的數(shù)據(jù)成員和成員函數(shù)。Personchar*name;char*id_card_no;boolgender;Studentcharstudent_no;Dateenroll_date;……FacultyDatehire_date;Degreedegree;……AdministratorDatehire_date;Rankrank;……4.1繼承的概念當(dāng)前第5頁\共有86頁\編于星期五\16點(diǎn)2、繼承目的代碼重用coderesue描述能力:類屬關(guān)系廣泛存在IsAvs.HasA3、有關(guān)概念

基類,超類

派生類,子類4.1繼承的概念當(dāng)前第6頁\共有86頁\編于星期五\16點(diǎn)4、派生類可實(shí)施的對(duì)基類的改變?cè)黾有碌臄?shù)據(jù)成員和成員函數(shù)。重載基類的成員函數(shù)。重定義基類已有的成員函數(shù)。改變基類成員在派生類中的訪問屬性。5、派生類不能繼承基類的以下內(nèi)容基類的構(gòu)造函數(shù)和析構(gòu)函數(shù)?;惖挠言瘮?shù)。靜態(tài)數(shù)據(jù)成員和靜態(tài)成員函數(shù)4.1繼承的概念當(dāng)前第7頁\共有86頁\編于星期五\16點(diǎn)4.2protected和繼承1、關(guān)于protected權(quán)限protected可以用來設(shè)置類成員的訪問權(quán)限,具有protected訪問權(quán)限的成員稱為保護(hù)成員。protected主要用于繼承,對(duì)于一個(gè)不被任何派生類繼承的類而言,protected訪問屬性與private完全相同。在繼承結(jié)構(gòu)中,基類的protected成員雖然不能被派生類的外部函數(shù)訪問,但卻能夠被其派生類直接訪問。當(dāng)前第8頁\共有86頁\編于星期五\16點(diǎn)4.2protected和繼承【例4-1】保護(hù)成員的例子//Eg4-1.cpp#include<iostream>usingnamespacestd;classB{private:inti;protected:intj;public:intk;};當(dāng)前第9頁\共有86頁\編于星期五\16點(diǎn)classD:publicB{//L1,此表示D從B派生public:voidf(){i=1; //L1,錯(cuò)誤

j=2; //L2,正確k=3; //L3,正確}};voidmain(){Bb;b.i=1; //L4,錯(cuò)誤b.j=2; //L5,錯(cuò)誤b.k=3;}當(dāng)前第10頁\共有86頁\編于星期五\16點(diǎn)4.2protected和繼承2、例4.1類繼承后的成員訪問權(quán)限當(dāng)前第11頁\共有86頁\編于星期五\16點(diǎn)4.2protected和繼承3、說明①一個(gè)類如果不被其他類繼承,則其protected和private成員具有相同的訪問屬性。只能被本類成員函數(shù)訪問,不能被類的外部函數(shù)訪問。②一個(gè)類如果被其他類繼承,派生類不能直接訪問它的private成員,但能夠直接訪問它的protected成員,這就是protected成員與private成員的區(qū)別。③盡管基類的public和protected成員都能被派生類直接訪問,但它們是有區(qū)別的。public成員能夠被類的外部函數(shù)直接訪問,而protected成員則不能。當(dāng)前第12頁\共有86頁\編于星期五\16點(diǎn)4.3

繼承方式1、C++的繼承類型可分為公有繼承、保護(hù)繼承和私有繼承,也稱為公有派生、保護(hù)派生和私有派生。不同繼承方式會(huì)不同程度地影響基類成員在派生類中的訪問權(quán)限。

當(dāng)前第13頁\共有86頁\編于星期五\16點(diǎn)4.3

繼承方式2、繼承語法形式classB{……};classD:[private|protected|public]B{

……};當(dāng)前第14頁\共有86頁\編于星期五\16點(diǎn)3、public繼承最常見的派生方式維持基類成員的可訪問性派生類不可直接訪問基類的private成員,可通過基類的共有成員函數(shù)訪問4.3

繼承方式當(dāng)前第15頁\共有86頁\編于星期五\16點(diǎn)例題ch4_2.cppclassbase{ intx;public: voidsetx(intn){ x=n; } intgetx(){ returnx;} voidshowx() { cout<<x<<endl;}};classderived:publicbase{ inty;public: voidsety(intn){ y=n; } voidsety(){ y=getx();} voidshowy() { cout<<y<<endl;}};Setx()Getx()Showx()xSetx()Getx()Showx()xSety()Gety()Showy()y接口私有數(shù)據(jù)basederived當(dāng)前第16頁\共有86頁\編于星期五\16點(diǎn)voidmain(){ derivedobj; obj.setx(10); obj.sety(20); obj.showx(); obj.showy(); obj.sety(); obj.showx(); obj.showy();}3.public繼承當(dāng)前第17頁\共有86頁\編于星期五\16點(diǎn)4.私有繼承Private基類的中的public成員在派生類中是private,private成員在派生類中不可訪問?!纠?】私有繼承的例子//Eg.cpp#include<iostream>usingnamespacestd;classBase{intx;public:voidsetx(intn){x=n;}intgetx(){returnx;}voidshowx(){cout<<x<<endl;}};當(dāng)前第18頁\共有86頁\編于星期五\16點(diǎn)classderived:privatebase{ inty;public: voidsety(intn){y=n; } voidsety(){ y=getx();} voidshowy() { cout<<y<<endl;}};voidmain(){ derivedobj; obj.setx(10);//cannotaccess obj.sety(20); obj.showx();//cannotaccess obj.showy(); }Setx()Getx()Showx()xSetx()Getx()Showx()xSety()Gety()Showy()y接口私有數(shù)據(jù)basederived當(dāng)前第19頁\共有86頁\編于星期五\16點(diǎn)4.2protected和繼承派生方式為protected的繼承稱為保護(hù)繼承,在這種繼承方式下,基類的public成員在派生類中會(huì)變成protected成員,基類的protected和private成員在派生類中保持原來的訪問權(quán)限。

【例4】保護(hù)繼承的例子。#include<iostream>usingnamespacestd;classBase{intx;protected:intgetx(){returnx;}public:voidsetx(intn){x=n;}voidshowx(){cout<<x<<endl;}};當(dāng)前第20頁\共有86頁\編于星期五\16點(diǎn)classDerived:protectedBase{inty;public:voidsety(intn){y=n;}voidsety(){y=getx();}//訪問基類的保護(hù)成員

voidshowy(){cout<<y<<endl;}};voidmain(){Derivedobj;obj.setx(10);//錯(cuò)誤

obj.sety(20);obj.showx(); //錯(cuò)誤,

obj.showy();}當(dāng)前第21頁\共有86頁\編于星期五\16點(diǎn)表4-1:基類成員在派生類中的訪問權(quán)限不能繼承的基類內(nèi)容1.構(gòu)造函數(shù)、析構(gòu)函數(shù)2.友員關(guān)系3.針對(duì)基類定義的一些特殊運(yùn)算符,如new等。派生類基類public繼承protected繼承private繼承publicprotectedprivatepublicprotectedprivatepublicprotectedprivatepublic√

√protected

√private

√當(dāng)前第22頁\共有86頁\編于星期五\16點(diǎn)4.4基類與派生類的關(guān)系、成員函數(shù)的重定義和名字隱藏派生類對(duì)基類成員函數(shù)的重定義或重載會(huì)影響基類成員函數(shù)在派生類中的可見性,基類的同名成員函數(shù)會(huì)被派生類重載的同名函數(shù)所隱藏?!纠?-3】派生類重載基類成員函數(shù)的例子。當(dāng)前第23頁\共有86頁\編于星期五\16點(diǎn)//Eg4-3.cpp#include<iostream>usingnamespacestd;classBase{intx;public:voidsetx(inti){x=i;}voidset(intn){x=n;}voidprint(){cout<<"Baseclass:x="<<x<<endl;}};當(dāng)前第24頁\共有86頁\編于星期五\16點(diǎn)classDerived:publicBase{intm,n;public:voidset(intp,intk){m=p;n=k;} //L1重載基類的成員函數(shù)set()voidset(inti,intj,intk){ //L2重載成員函數(shù)set()Base::set(i); //L3調(diào)用基類成員函數(shù)set()m=j;n=k;}voidprint(){ //L4重定義基類的成員函數(shù)print()Base::print();cout<<"DerivedClass:m="<<m<<endl;cout<<"DerivedClass:n="<<n<<endl;}};當(dāng)前第25頁\共有86頁\編于星期五\16點(diǎn)voidmain(){Derivedd; //L5d.set(1,3); //L6d.print(); //L7d.set(5,6,7); //L8d.print(); //L9//d.set(10); //L10,錯(cuò)誤,只能是d.Base::set(10)d.Base::print(); //L11d.setx(8); //L12}當(dāng)前第26頁\共有86頁\編于星期五\16點(diǎn)2、派生類和基類的關(guān)系派生類繼承了基類的所有成員,盡管有些繼承的成員是不可訪問的派生類可以:添加新的數(shù)據(jù)成員和/或函數(shù)成員修改繼承的函數(shù)成員的行為(overloading)覆蓋繼承的函數(shù)成員(overriding)classBase {basemembers;};classDerived:Base {newmembers;};basemembersnewmembersthis指針Derivedmembers當(dāng)前第27頁\共有86頁\編于星期五\16點(diǎn)派生類對(duì)基類成員的訪問形式通過派生類對(duì)象直接訪問基類成員在派生類成員函數(shù)中直接訪問基類成員通過基類名字限定訪問被重載的基類成員名4.4.2基類成員訪問當(dāng)前第28頁\共有86頁\編于星期五\16點(diǎn)4.4基類與派生類的關(guān)系【例】在派生類中訪問基類成員。//Eg.cpp#include<iostream>usingnamespacestd;classB{intx;public:voidset(inti){x=i;}voidsetx(inti){x=i;}voidprintx(){cout<<"x="<<x<<endl;}};當(dāng)前第29頁\共有86頁\編于星期五\16點(diǎn)classD:publicB{inty;public:voidsety(intp){y=p;}voidprinty(){cout<<"y="<<y<<endl;}voidsetxy(inti,intj){setx(i); //L1在派生類成員函數(shù)中直接訪問基類成員

y=j;}voidset(inti,intj){B::set(i); //L2訪問基類set成員

y=j;}};voidmain(){Dobj;obj.setx(2); //L3訪問基類成員

obj.printx(); //L4訪問基類成員,輸出x=2obj.sety(3); //L5訪問派生類成員

obj.set(1,2); //L6訪問派生類set成員

obj.B::set(3); //L7訪問基類set成員}當(dāng)前第30頁\共有86頁\編于星期五\16點(diǎn)4.5構(gòu)造函數(shù)和析構(gòu)函數(shù)類對(duì)象成員的構(gòu)造先構(gòu)造成員再構(gòu)造自身(調(diào)用構(gòu)造函數(shù))例題ch.cpp當(dāng)前第31頁\共有86頁\編于星期五\16點(diǎn)classA{public: A(){cout<<"ConstructingA"<<endl;} ~A(){cout<<"DestructingA"<<endl;}};classB{public: B(){cout<<"ConstructingB"<<endl;} ~B(){cout<<"DestructingB"<<endl;}};當(dāng)前第32頁\共有86頁\編于星期五\16點(diǎn)classC{public: C(){cout<<"ConstructingC"<<endl;} ~C(){cout<<"DestructingC"<<endl;} Bb; Aa;};voidmain(){ Cc;}ConstructingBConstructingAConstructingCDestructingCDestructingADestructingB如果:classB:publicA{}classC:publicB{}結(jié)果又當(dāng)如何?當(dāng)前第33頁\共有86頁\編于星期五\16點(diǎn)4.5.1派生類構(gòu)造函數(shù)、析構(gòu)函數(shù)的定義和調(diào)用次序派生類可能有多個(gè)基類,也可能包括多個(gè)成員對(duì)象,在創(chuàng)建派生類對(duì)象時(shí),派生類的構(gòu)造函數(shù)除了要負(fù)責(zé)本類成員的初始化外,還要調(diào)用基類和成員對(duì)象的構(gòu)造函數(shù),并向它們傳遞參數(shù),以完成基類子對(duì)象和成員對(duì)象的建立和初始化。派生類只能采用構(gòu)造函數(shù)初始化列表的方式向基類或成員對(duì)象的構(gòu)造函數(shù)傳遞參數(shù),形式如下:派生類構(gòu)造函數(shù)名(參數(shù)表):基類構(gòu)造函數(shù)名(參數(shù)表),成員對(duì)象名1(參數(shù)表),…{//……}當(dāng)前第34頁\共有86頁\編于星期五\16點(diǎn)4.5.1派生類構(gòu)造函數(shù)、析構(gòu)函數(shù)的定義和調(diào)用次序【例4-4】派生類Derived以構(gòu)造函數(shù)初始化列表的方式向基類構(gòu)造函數(shù)提供參數(shù)。//Eg4-4.cpp#include<iostream>usingnamespacestd;classBase{ intx;public:

Base(inta){ //L1 x=a; cout<<"ConstructingBase:x="<<x<<endl; }~Base(){cout<<"DestructingBase:x="<<x<<endl;}};當(dāng)前第35頁\共有86頁\編于星期五\16點(diǎn)classDerived:publicBase{ intz;public:Derived(inti,intj,intk):Base(i),b(j){ //L2 z=k; cout<<"ConstructingDerived:z="<<z<<endl; }~Derived(){cout<<"DestructingDerived:z="<<z<<endl;}

Baseb; //L4};voidmain(){Derivedd(1,2,3); //L6}當(dāng)前第36頁\共有86頁\編于星期五\16點(diǎn)派生類對(duì)象的構(gòu)造先構(gòu)造基類再構(gòu)造成員最后構(gòu)造自身(調(diào)用構(gòu)造函數(shù))基類構(gòu)造順序由派生層次決定:最遠(yuǎn)的基類最先構(gòu)造成員構(gòu)造順序和定義順序符合析構(gòu)函數(shù)的析構(gòu)順序與構(gòu)造相反4.5.1派生類構(gòu)造函數(shù)、析構(gòu)函數(shù)的定義和調(diào)用次序當(dāng)前第37頁\共有86頁\編于星期五\16點(diǎn)例題ch.cppclassA{public: A(){cout<<"ConstructingA"<<endl;} ~A(){cout<<"DestructingA"<<endl;}};classB{public: B(){cout<<"ConstructingB"<<endl;} ~B(){cout<<"DestructingB"<<endl;}};當(dāng)前第38頁\共有86頁\編于星期五\16點(diǎn)classC{public: C(){cout<<"ConstructingC"<<endl;} ~C(){cout<<"DestructingC"<<endl;}};當(dāng)前第39頁\共有86頁\編于星期五\16點(diǎn)classD:publicC{public: D(){cout<<"ConstructingD"<<endl;} ~D(){cout<<"DestructingD"<<endl;} Bb; Aa; Cc;};voidmain(){ Dd;}ConstructingCConstructingBConstructingAConstructingCConstructingDDestructingDDestructingCDestructingADestructingBDestructingC當(dāng)前第40頁\共有86頁\編于星期五\16點(diǎn)4.5.2構(gòu)造函數(shù)和析構(gòu)函數(shù)的構(gòu)造規(guī)則1、派生類可以不定義構(gòu)造函數(shù)的情況當(dāng)具有下述情況之一時(shí),派生類可以不定義構(gòu)造函數(shù)?;悰]有定義任何構(gòu)造函數(shù)?;惥哂腥笔?shù)的構(gòu)造函數(shù)?;惥哂袩o參構(gòu)造函數(shù)。當(dāng)前第41頁\共有86頁\編于星期五\16點(diǎn)【例4-5】沒有構(gòu)造函數(shù)的派生類。//Eg4-5.cpp#include<iostream>usingnamespacestd;classA{public:A(){cout<<"ConstructingA"<<endl;}~A(){cout<<"DestructingA"<<endl;}};classB:publicA{public:~B(){cout<<"DestructingB"<<endl;}};voidmain(){Bb;}當(dāng)前第42頁\共有86頁\編于星期五\16點(diǎn)4.5.2構(gòu)造函數(shù)和析構(gòu)函數(shù)的構(gòu)造規(guī)則2、派生類必須定義構(gòu)造函數(shù)的情況

當(dāng)基類或成員對(duì)象所屬類只含有帶參數(shù)的構(gòu)造函數(shù)時(shí),即使派生類本身沒有數(shù)據(jù)成員要初始化,它也必須定義構(gòu)造函數(shù),并以構(gòu)造函數(shù)初始化列表的方式向基類和成員對(duì)象的構(gòu)造函數(shù)傳遞參數(shù),以實(shí)現(xiàn)基類子對(duì)象和成員對(duì)象的初始化。當(dāng)前第43頁\共有86頁\編于星期五\16點(diǎn)4.5.2構(gòu)造函數(shù)和析構(gòu)函數(shù)的構(gòu)造規(guī)則【例4-6】派生類構(gòu)造函數(shù)的定義。//Eg4-6.cpp#include<iostream>usingnamespacestd;classPoint{protected:intx,y;public:Point(inta,intb=0){x=a;y=b;cout<<"constructingpoint("<<x<<","<<y<<")"<<endl;}};當(dāng)前第44頁\共有86頁\編于星期五\16點(diǎn)classLine:publicPoint{protected:intlen;public:Line(inta,intb,intl):Point(a,b){ //構(gòu)造函數(shù)初始化列表

len=l;cout<<"ConstructingLine,len..."<<len<<endl;}};voidmain(){LineL1(1,2,3);}當(dāng)前第45頁\共有86頁\編于星期五\16點(diǎn)3、派生類的構(gòu)造函數(shù)只負(fù)責(zé)直接基類的初始化C++語言標(biāo)準(zhǔn)有一條規(guī)則:如果派生類的基類同時(shí)也是另外一個(gè)類的派生類,則每個(gè)派生類只負(fù)責(zé)它的直接基類的構(gòu)造函數(shù)調(diào)用。這條規(guī)則表明當(dāng)派生類的直接基類只有帶參數(shù)的構(gòu)造函數(shù),但沒有默認(rèn)構(gòu)造函數(shù)時(shí)(包括缺省參數(shù)和無參構(gòu)造函數(shù)),它必須在構(gòu)造函數(shù)的初始化列表中調(diào)用其直接基類的構(gòu)造函數(shù),并向基類的構(gòu)造函數(shù)傳遞參數(shù),以實(shí)現(xiàn)派生類對(duì)象中的基類子對(duì)象的初始化。這條規(guī)則有一個(gè)例外情況,當(dāng)派生類存在虛基類時(shí),所有虛基類都由最后的派生類負(fù)責(zé)初始化。4.5.2構(gòu)造函數(shù)和析構(gòu)函數(shù)的構(gòu)造規(guī)則當(dāng)前第46頁\共有86頁\編于星期五\16點(diǎn)【例4-7】當(dāng)同時(shí)存在直接基類和間接基類時(shí),每個(gè)派生類只負(fù)責(zé)其直接基類的構(gòu)造。//Eg4-7.cpp#include<iostream>usingnamespacestd;classA{intx;public:A(intaa){x=aa;cout<<"ConstructingA"<<endl;}~A(){cout<<"DestructingA"<<endl;}};當(dāng)前第47頁\共有86頁\編于星期五\16點(diǎn)classB:publicA{public:B(intx):A(x){cout<<"ConstructingB"<<endl;}};classC:publicB{public:C(inty):B(y){cout<<"ConstructingC"<<endl;}};voidmain(){Cc(1);}當(dāng)前第48頁\共有86頁\編于星期五\16點(diǎn)4、構(gòu)造函數(shù)的調(diào)用時(shí)間和次序當(dāng)派生類具有多個(gè)基類和多個(gè)對(duì)象成員,它們的構(gòu)造函數(shù)將在創(chuàng)建派生類對(duì)象時(shí)被調(diào)用,調(diào)用次序如下:基類構(gòu)造函數(shù)→對(duì)象成員構(gòu)造函數(shù)→派生類構(gòu)造函數(shù)4.5.2構(gòu)造函數(shù)和析構(gòu)函數(shù)的構(gòu)造規(guī)則當(dāng)前第49頁\共有86頁\編于星期五\16點(diǎn)(1)當(dāng)有多個(gè)基類時(shí),將按照它們?cè)诶^承方式中的聲明次序調(diào)用,與它們?cè)跇?gòu)造函數(shù)初始化列表中的次序無關(guān)。當(dāng)基類A本身又是另一個(gè)類B的派生類時(shí),則先調(diào)用基類B的構(gòu)造函數(shù),再調(diào)用基類A的構(gòu)造函數(shù)。(2)當(dāng)有多個(gè)對(duì)象成員時(shí),將按它們?cè)谂缮愔械穆暶鞔涡蛘{(diào)用,與它們?cè)跇?gòu)造函數(shù)初始化列表中的次序無關(guān)。(3)當(dāng)構(gòu)造函數(shù)初始化列表中的基類和對(duì)象成員的構(gòu)造函數(shù)調(diào)用完成之后,才執(zhí)行派生類構(gòu)造函數(shù)體中的程序代碼。4.5.2構(gòu)造函數(shù)和析構(gòu)函數(shù)的構(gòu)造規(guī)則當(dāng)前第50頁\共有86頁\編于星期五\16點(diǎn)【例4-8】構(gòu)造函數(shù)的調(diào)用次序驗(yàn)證。//Eg4-8.cpp#include<iostream>usingnamespacestd;classA{intx;public:A(inti=0){x=i;cout<<"A-----"<<x<<endl;}};classB{inty;public:B(inti){y=i;cout<<"B-----"<<y<<endl;}};當(dāng)前第51頁\共有86頁\編于星期五\16點(diǎn)classC{intz;public:C(inti){z=i;cout<<"C-----"<<z<<endl;}};classD:publicB{public:Cc1,c2;Aa0,a4;D():a4(4),c2(2),c1(1),B(1){cout<<"D-----5"<<endl;}};voidmain(){Dd;}當(dāng)前第52頁\共有86頁\編于星期五\16點(diǎn)4.6多重繼承4.6.1多繼承的概念和應(yīng)用C++允許一個(gè)類從一個(gè)或多個(gè)基類派生。如果一個(gè)類只有一個(gè)基類,就稱為單一繼承。如果一個(gè)類具有兩個(gè)或兩個(gè)以上的基類,就稱為多重繼承。多繼承的形式如下:class派生類名:[繼承方式]基類名1,[繼承方式]基類名2,

…{……};其中,繼承方式可以是public、protected、private當(dāng)前第53頁\共有86頁\編于星期五\16點(diǎn)4.6.1多繼承的概念和應(yīng)用當(dāng)前第54頁\共有86頁\編于星期五\16點(diǎn)【例4-9】上圖的簡(jiǎn)單程序。//Eg4-9.cpp#include<iostream>usingnamespacestd;classBase1{private:intx;protected:intgetx(){returnx;}public:voidsetx(inta=1){x=a;}};4.6.1多繼承的概念和應(yīng)用當(dāng)前第55頁\共有86頁\編于星期五\16點(diǎn)classBase2{private:inty;public:voidsety(inta){y=a;}intgety(){returny;}};classBase3{private:intz;public:voidsetz(inta){z=a;}intgetz(){returnz;}};當(dāng)前第56頁\共有86頁\編于星期五\16點(diǎn)classDerived:publicBase1,publicBase2,publicBase3{private:intd;public:voidsetd(inta){d=a;}voiddisplay();};voidDerived::display(){cout<<"Base1....x="<<getx()<<endl;cout<<"Base2....y="<<gety()<<endl;cout<<"Base3....z="<<getz()<<endl;cout<<"Derived..d="<<d<<endl;}voidmain(){Derivedobj;obj.setx(1);obj.sety(2);obj.setz(3);obj.setd(4);obj.display();}當(dāng)前第57頁\共有86頁\編于星期五\16點(diǎn)4.6.2多繼承下的二義性在多繼承方式下,派生類繼承了多個(gè)基類的成員,當(dāng)兩個(gè)不同基類擁有同名成員時(shí),容易產(chǎn)生名字沖突問題。【例4-10】類A和類B是MI的基類,它們都有一個(gè)成員函數(shù)f,在類MI中就有通過繼承而來的兩個(gè)同名成員函數(shù)f。當(dāng)前第58頁\共有86頁\編于星期五\16點(diǎn)//Eg4-10.cpp#include<iostream>usingnamespacestd;classA{public:voidf(){cout<<"FromA"<<endl;}};classB{public:voidf(){cout<<"FromB"<<endl;}};classMI:publicA,publicB{public:voidg(){cout<<"FromMI"<<endl;}};voidmain(){MImi;mi.f(); //錯(cuò)誤

mi.A::f(); //正確}當(dāng)前第59頁\共有86頁\編于星期五\16點(diǎn)4.6.3多繼承的構(gòu)造函數(shù)與析構(gòu)函數(shù)派生類必須負(fù)責(zé)為每個(gè)基類的構(gòu)造函數(shù)提供初始化參數(shù),構(gòu)造的方法和原則與單繼承相同。構(gòu)造函數(shù)的調(diào)用次序仍然是先基類,再對(duì)象成員,然后才是派生類的構(gòu)造函數(shù)?;悩?gòu)造函數(shù)的調(diào)用次序與它們?cè)诒焕^承時(shí)的聲明次序相同,與它們?cè)谂缮悩?gòu)造函數(shù)的初始化列表中的次序沒有關(guān)系。多繼承方式下的析構(gòu)函數(shù)調(diào)用次序仍然與構(gòu)造函數(shù)的調(diào)用次序相反。當(dāng)前第60頁\共有86頁\編于星期五\16點(diǎn)【例4-11】類Base1、Base2、Base3、Derived的繼承關(guān)系如圖所示,驗(yàn)證其構(gòu)造函數(shù)和析構(gòu)函數(shù)的調(diào)用次序。4.6.3多繼承的構(gòu)造函數(shù)與析構(gòu)函數(shù)當(dāng)前第61頁\共有86頁\編于星期五\16點(diǎn)//Eg4-11.cpp#include<iostream>usingnamespacestd;classBase1{private:intx;public:Base1(inta=1){x=a;cout<<"Base1constructorx="<<x<<endl;}~Base1(){cout<<"Base1destructor..."<<endl;}};當(dāng)前第62頁\共有86頁\編于星期五\16點(diǎn)classBase2{private:inty;public:Base2(inta){y=a;cout<<"Base2constructory="<<y<<endl;}~Base2(){cout<<"Base2destructor..."<<endl;}};當(dāng)前第63頁\共有86頁\編于星期五\16點(diǎn)classBase3{private:intz;public:Base3(inta){z=a;cout<<"Base3constructorz="<<z<<endl;}~Base3(){cout<<"Base3destructor..."<<endl;}};當(dāng)前第64頁\共有86頁\編于星期五\16點(diǎn)classDerived:publicBase1,protectedBase2,privateBase3{private:inty;public:Derived(inta,intb,intc):Base3(b),Base2(a){y=c;cout<<"Derivedconstructory="<<y<<endl;}~Derived(){cout<<"Deriveddestructor..."<<endl;}};voidmain(){Derivedd(2,3,4);}當(dāng)前第65頁\共有86頁\編于星期五\16點(diǎn)1.虛擬繼承引入的原因:重復(fù)基類派生類間接繼承同一基類使得間接基類(Person)在派生類中有多份拷貝,引發(fā)二義性。DeptHeadFacultyPersonname…AdministratorPersonname

…4.7繼擬繼承當(dāng)前第66頁\共有86頁\編于星期五\16點(diǎn)虛擬基類在派生類中只存在一份拷貝,解決了基類數(shù)據(jù)成員的二義性問題4.7繼擬繼承當(dāng)前第67頁\共有86頁\編于星期五\16點(diǎn)2、虛擬繼承virtualinheritance的定義語法classderived_class:virtual[…]base_class虛基類virtualbaseclass被虛擬繼承的基類在其所以的派生類中,僅出現(xiàn)一次4.7繼擬繼承當(dāng)前第68頁\共有86頁\編于星期五\16點(diǎn)classA{public: voidvf(){ cout<<"IcomefromclassA"<<endl; }};classB:publicA{};classC:publicA{};classD:publicB,publicC{};voidmain(){ Dd; d.vf(); //error}ABCDVf()Vf()Vf()B.A::Vf()C.A::Vf()AVf()【例】類A是類B、C的虛基類,類D從類B、C繼承,在類D中調(diào)用基類A的成員不會(huì)產(chǎn)生二義性。當(dāng)前第69頁\共有86頁\編于星期五\16點(diǎn)classA{public: voidvf(){ cout<<"IcomefromclassA"<<endl; }};classB:virtualpublicA{};classC:virtualpublicA{};classD:publicB,publicC{};voidmain(){ Dd; d.vf(); //okay}ABCDVf()Vf()Vf()A::Vf()將【例】改為虛擬繼承不會(huì)產(chǎn)生二義性。當(dāng)前第70頁\共有86頁\編于星期五\16點(diǎn)3、虛擬繼承的構(gòu)造次序虛基類的初始化與一般的多重繼承的初始化在語法上是一樣的,但構(gòu)造函數(shù)的調(diào)用順序不同;若基類由虛基類派生而來,則派生類必須提供對(duì)間接基類的構(gòu)造(即在構(gòu)造函數(shù)初始列表中構(gòu)造虛基類,無論此虛基類是直接還是間接基類)調(diào)用順序的規(guī)定:先調(diào)用虛基類的構(gòu)造函數(shù),再調(diào)用非虛基類的構(gòu)造函數(shù)若同一層次中包含多個(gè)虛基類,這些虛基類的構(gòu)造函數(shù)按它們的說明的次序調(diào)用若虛基類由非基類派生而來,則仍然先調(diào)用基類構(gòu)造函數(shù),再調(diào)用派生類構(gòu)造函數(shù)4.7繼擬繼承當(dāng)前第71頁\共有86頁\編于星期五\16點(diǎn)【例4-12】虛基類的執(zhí)行次序分析。//Eg4-12.cpp#include<iostream>usingnamespacestd;classA{inta;public:A(){cout<<"ConstructingA"<<endl;}};classB{public:B(){cout<<"ConstructingB"<<endl;}};4.7繼擬繼承當(dāng)前第72頁\共有86頁\編于星期五\16點(diǎn)classB1:virtualpublicB,virtualpublicA{public:B1(inti){cout<<"ConstructingB1"<<endl;}};classB2:publicA,virtualpublicB{public:B2(intj){cout<<"ConstructingB2"<<endl;}};classD:publicB1,publicB2{public:D(intm,intn):B1(m),B2(n){cout<<"ConstructingD"<<endl;}Aa;};

voidmain(){Dd(1,2);}當(dāng)前第73頁\共有86頁\編于星期五\16點(diǎn)4、虛基類由最終派生類初始化在沒有虛擬繼承的情況下,每個(gè)派生類的構(gòu)造函數(shù)只負(fù)責(zé)其直接基類的初始化。但在虛擬繼承方式下,虛基類則由最終派生類的構(gòu)造函數(shù)負(fù)責(zé)初始化。

在虛擬繼承方式下,若最終派生類的構(gòu)造函數(shù)沒有明確調(diào)用虛基類的構(gòu)造函數(shù),編譯器就會(huì)嘗試調(diào)用虛基類不需要參數(shù)的構(gòu)造函數(shù)(包括缺省、無參和缺省參數(shù)的構(gòu)造函數(shù)),如果沒找到就會(huì)產(chǎn)生編譯錯(cuò)誤。4.7繼擬繼承當(dāng)前第74頁\共有86頁\編于星期五\16點(diǎn)【例4-13】類A是類B、C的虛基類,類ABC從B、C派生,是繼承結(jié)構(gòu)中的最終派生類,它負(fù)責(zé)虛基類A的初始化。//Eg4-13.cpp#include<iostream.h>classA{inta;public:A(intx){a=x;cout<<"VirtualBassA..."<<endl;}};當(dāng)前第75頁\共有86頁\編于星期五\16點(diǎn)classB:virtualpublicA{public:B(inti):A(i){cout<<"VirtualBassB..."<<endl;}};classC:virtualpublicA{intx;public:C(inti):A(i){cout<<"ConstructingC..."<<endl;x=i;}};classABC:publicC,publicB{public:ABC(inti,intj,intk):C(i),B(j),A(i)//L1,這里必須對(duì)A進(jìn)行初始化

{cout<<"ConstructingABC..."<<endl;}};voidmain(){ABCobj(1,2,3);}當(dāng)前第76頁\共有86頁\編于星期五\16點(diǎn)4.8基類與派生類對(duì)象的關(guān)系

基類對(duì)象與派生類對(duì)象之間存在賦值相容性。包括以下幾種情況:把派生類對(duì)象賦值給基類對(duì)象。把派生類對(duì)象的地址賦值給基類指針。用派生類對(duì)象初始化基類對(duì)象的引用。反之則不行,即不能把基類對(duì)象賦值給派生類對(duì)象;不能把基類對(duì)象的地址賦值給派生類對(duì)象的指針;也不能把基類對(duì)象作為派生對(duì)象的引用。當(dāng)前第77頁\共有86頁\編于星期五\16點(diǎn)【例4-14】把派生類對(duì)象賦值給基類對(duì)象的例子。//Eg4-14cpp#include<iostream>usingname

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(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)論