C語言程序設(shè)計繼承與派生_第1頁
C語言程序設(shè)計繼承與派生_第2頁
C語言程序設(shè)計繼承與派生_第3頁
C語言程序設(shè)計繼承與派生_第4頁
C語言程序設(shè)計繼承與派生_第5頁
已閱讀5頁,還剩54頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

會計學(xué)1C語言程序設(shè)計繼承與派生2類的繼承與派生保持已有類的特性而構(gòu)造新類的過程稱為繼承。在已有類的基礎(chǔ)上新增自己的特性而產(chǎn)生新類的過程稱為派生。被繼承的已有類稱為基類(或父類)。派生出的新類稱為派生類。類的繼承與派生第1頁/共62頁3繼承與派生問題舉例類的繼承與派生第2頁/共62頁4繼承與派生的目的繼承的目的:實現(xiàn)代碼重用。派生的目的:當(dāng)新的問題出現(xiàn),原有程序無法解決(或不能完全解決)時,需要對原有程序進(jìn)行改造。類的繼承與派生第3頁/共62頁5派生類的聲明class派生類名:繼承方式基類名1{

成員聲明;}類的繼承與派生第4頁/共62頁6繼承方式不同繼承方式的影響主要體現(xiàn)在:派生類成員對基類成員的訪問權(quán)限通過派生類對象對基類成員的訪問權(quán)限三種繼承方式公有繼承私有繼承保護(hù)繼承類成員的訪問控制第5頁/共62頁7公有繼承(public)基類的public和protected成員的訪問屬性在派生類中保持不變。(即:派生類中的成員函數(shù)可以直接訪問基類中的public和protected成員)派生類的成員函數(shù)不能直接訪問基類的private成員。通過派生類的對象只能訪問基類的public成員。類成員的訪問控制第6頁/共62頁8例7-1公有繼承舉例classPoint

{public: voidInitP(floatxx=0,floatyy=0){X=xx;Y=yy;} voidMove(floatxOff,floatyOff){X+=xOff;Y+=yOff;} floatGetX(){returnX;} floatGetY(){returnY;}private: floatX,Y;};類成員的訪問控制第7頁/共62頁9classRectangle:publicPoint

{public:voidInitR(floatx,floaty,floatw,floath){InitP(x,y);W=w;H=h;} floatGetH(){returnH;} floatGetW(){returnW;}private: floatW,H;};類成員的訪問控制第8頁/共62頁10#include<iostream>usingnamespacestd;voidmain(){Rectanglerect;rect.InitR(2,3,20,10); rect.Move(3,2); cout<<rect.GetX()<<','<<rect.GetY()<<',' <<rect.GetW()<<','<<rect.GetH();}類成員的訪問控制繼承的方法第9頁/共62頁11私有繼承(private)基類的public和protected成員都以private身份出現(xiàn)在派生類中。(即派生類中的成員函數(shù)可以直接訪問基類中的public和protected成員)派生類的成員函數(shù)不能直接訪問基類的private成員。通過派生類的對象不能直接訪問基類中的任何成員。類成員的訪問控制第10頁/共62頁12例7-2私有繼承舉例類成員的訪問控制classRectangle:privatePoint

{public:voidInitR(floatx,floaty,floatw,floath){InitP(x,y);W=w;H=h;} floatGetH(){returnH;} floatGetW(){returnW;}private: floatW,H;};第11頁/共62頁13#include<iostream>usingnamespacestd;voidmain(){Rectanglerect; rect.InitR(2,3,20,10); rect.Move(3,2); cout<<rect.GetX()<<','<<rect.GetY()<<',' <<rect.GetH()<<','<<rect.GetW();}類成員的訪問控制非法訪問第12頁/共62頁14

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: floatW,H;

};類成員的訪問控制第13頁/共62頁15#include<iostream>usingnamespacestd;voidmain(){Rectanglerect; rect.InitR(2,3,20,10); rect.Move(3,2); cout<<rect.GetX()<<','<<rect.GetY()<<',' <<rect.GetH()<<','<<rect.GetW();}類成員的訪問控制訪問派生類自身的方法第14頁/共62頁16保護(hù)繼承(protected)基類的public和protected成員都以protected身份出現(xiàn)在派生類中。(即派生類中的成員函數(shù)可以直接訪問基類中的public和protected成員)派生類的成員函數(shù)不能直接訪問基類的private成員。通過派生類的對象不能直接訪問基類中的任何成員。類成員的訪問控制第15頁/共62頁17#include<iostream>usingnamespacestd;classA{protected:intx;};classB:protectedA{public:voidFunction();};classC:privateB{public:voidFunction();};voidB::Function(){x=5;cout<<x<<endl;}voidC::Function(){x=15;cout<<x<<endl;}voidmain(){Bb;b.Function();Cc;c.Function();}第16頁/共62頁18#include<iostream>usingnamespacestd;classA{protected:intx;};classB:protectedA{public:voidFunction();};classC:privateB{public:voidFunction();};voidB::Function(){x=5;cout<<x<<endl;}voidC::Function(){x=15;cout<<x<<endl;}voidmain(){Bb;b.Function();Cc;c.Function();}protectedprivatex=15;cout<<x<<endl;第17頁/共62頁19publicprotectedprivatepublicpublicprotected隔離protectedprotectedprotected隔離privateprivateprivate隔離基類訪問屬性繼承方式基類成員在派生類中的訪問控制屬性第18頁/共62頁20類型兼容規(guī)則一個公有派生類的對象在使用上可以被當(dāng)作基類的對象,反之則禁止。具體表現(xiàn)在:派生類的對象可以賦值給基類對象。派生類的對象可以初始化基類的引用。派生類對象的地址可以賦值給指向基類的指針。替代之后,派生類對象就可以作為基類的對象使用,但只能使用從基類繼承的成員。派生類對象發(fā)揮基類對象的作用。類型兼容第19頁/共62頁類型兼容#include<iostream>usingnamespacestd;classB0{public:voiddisplay(){cout<<"B0::display()"<<endl;} };classB1:publicB0

{public:voiddisplay(){cout<<"B1::display()"<<endl;}voidoutput(){cout<<"classB1B1::display()"<<endl;}};第20頁/共62頁類型兼容voidmain() {B0b0; B1b1; b0.display();b0=b1;b0.display();b1.display();b0.output();b1.output();}b0.display();B0::display()b0.display();b1.display();b0.output();b1.output();B0::display()B1::display()編譯錯誤classB1B1::display()P219例7-4第21頁/共62頁23基類與派生類的對應(yīng)關(guān)系單繼承派生類只從一個基類派生。多繼承派生類從多個基類派生。多重派生由一個基類派生出多個不同的派生類。多層派生派生類又作為基類,繼續(xù)派生新的類。單繼承與多繼承第22頁/共62頁24多繼承時派生類的聲明class派生類名:繼承方式1基類名1,繼承方式2基類名2,...{

成員聲明;}注意:每一個“繼承方式”,只用于限制其后的基類。單繼承與多繼承第23頁/共62頁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;};單繼承與多繼承第24頁/共62頁voidA::setA(intx){a=x;}voidB::setB(intx){b=x;}voidC::setC(intx,inty,intz){setA(x);

setB(y);c=z;}//其他函數(shù)實現(xiàn)略voidmain(){Cobj;obj.setA(5);obj.showA();obj.setC(6,7,9);obj.showC();

obj.setB(6);obj.showB();

}obj.setB(6);obj.showB();第25頁/共62頁27繼承時的構(gòu)造函數(shù)基類的構(gòu)造函數(shù)不被繼承,派生類中需要聲明自己的構(gòu)造函數(shù)。聲明構(gòu)造函數(shù)時,只需要對本類中新增成員進(jìn)行初始化,對繼承來的基類成員的初始化,自動調(diào)用基類構(gòu)造函數(shù)完成。派生類的構(gòu)造、析構(gòu)函數(shù)第26頁/共62頁28繼承時的構(gòu)造函數(shù)派生類的構(gòu)造、析構(gòu)函數(shù)當(dāng)基類中有默認(rèn)形式的構(gòu)造函數(shù)或帶默認(rèn)形參值的構(gòu)造函數(shù)時,派生類構(gòu)造函數(shù)可以不向基類構(gòu)造函數(shù)傳遞參數(shù)。若基類中未聲明構(gòu)造函數(shù),派生類中也可以不聲明,全采用默認(rèn)形式構(gòu)造函數(shù)。當(dāng)基類聲明有帶形參的構(gòu)造函數(shù)時,派生類也應(yīng)聲明帶形參的構(gòu)造函數(shù),并將參數(shù)傳遞給基類構(gòu)造函數(shù)。第27頁/共62頁29單一繼承時的構(gòu)造函數(shù)派生類的構(gòu)造、析構(gòu)函數(shù)classB{B();B(inti);…}classC:publicB{C();C(inti,intj)}…派生類C的構(gòu)造函數(shù)有以下幾種實現(xiàn)方式:C::C(){}或C::C(inti,intj){…}表示先調(diào)用B類默認(rèn)的構(gòu)造函數(shù)或帶默認(rèn)形參值的構(gòu)造函數(shù)初始化B類數(shù)據(jù)成員。C::C(inti,intj):B(i){…}表示先調(diào)用B類帶參數(shù)的構(gòu)造函數(shù)初始化B類數(shù)據(jù)成員。第28頁/共62頁#include<iostream>usingnamespacestd;classB{public:B();B(inti); private:intb;};classC:publicB{public:C();C(inti,intj);private:intc;};B::B(){b=0;cout<<"B'sdefaultconstructorcalled."<<endl;}B::B(inti){b=i;cout<<"B'sconstructorcalled."<<b<<endl;}C::C(){c=0;cout<<"C'sdefaultconstructorcalled."<<endl;}C::C(inti,intj):B(i){c=j;cout<<"C'sconstructorcalled."<<c<<endl;}voidmain(){Cobj(3,5);}第29頁/共62頁31多繼承時的構(gòu)造函數(shù)派生類名::派生類名(參數(shù)總表):基類名1(參數(shù)),基類名2(參數(shù)),...,基類名n(參數(shù)),對象數(shù)據(jù)成員的初始化{

本類成員初始化賦值語句;

};派生類的構(gòu)造、析構(gòu)函數(shù)第30頁/共62頁32構(gòu)造函數(shù)的調(diào)用順序1.調(diào)用基類構(gòu)造函數(shù),調(diào)用順序按照它們被繼承時聲明的順序(從左向右)。2.調(diào)用成員對象的構(gòu)造函數(shù),調(diào)用順序按照它們在類中聲明的順序。3.派生類的構(gòu)造函數(shù)體中的內(nèi)容。P222例7-5派生類的構(gòu)造、析構(gòu)函數(shù)第31頁/共62頁33拷貝構(gòu)造函數(shù)若建立派生類對象時調(diào)用默認(rèn)拷貝構(gòu)造函數(shù),則編譯器將自動調(diào)用基類的默認(rèn)拷貝構(gòu)造函數(shù)。若編寫派生類的拷貝構(gòu)造函數(shù),則需要為基類相應(yīng)的拷貝構(gòu)造函數(shù)傳遞參數(shù)。例如:C::C(C&c1):B(c1){…}派生類的構(gòu)造、析構(gòu)函數(shù)第32頁/共62頁派生類的構(gòu)造、析構(gòu)函數(shù)#include<iostream>usingnamespacestd;classB{public:B(inti);B(B&);~B(); private:intb;};classC:publicB{public:C(inti,intj);C(C&);~C(); private:intc;};第33頁/共62頁35派生類的構(gòu)造、析構(gòu)函數(shù)B::B(B&b1){b=0;cout<<"B'scopyconstructorcalled."<<endl;}B::B(inti){b=i;cout<<"B'sconstructorcalled."<<b<<endl;}B::~B(){cout<<"B'sdestructorcalled."<<endl;}第34頁/共62頁36派生類的構(gòu)造、析構(gòu)函數(shù)C::C(C&c1):B(c1){c=0;cout<<"C'scopyconstructorcalled."<<endl;}C::C(inti,intj):B(i){c=j;cout<<"C'sconstructorcalled."<<c<<endl;}C::~C(){cout<<"C'sdestructorcalled."<<endl;}voidmain(){Cobj(3,5);Cobj2(obj);}第35頁/共62頁37派生類的構(gòu)造、析構(gòu)函數(shù)第36頁/共62頁38繼承時的析構(gòu)函數(shù)析構(gòu)函數(shù)也不被繼承,派生類自行聲明聲明方法與一般(無繼承關(guān)系時)類的析構(gòu)函數(shù)相同。不需要顯式地調(diào)用基類的析構(gòu)函數(shù),系統(tǒng)會自動隱式調(diào)用。析構(gòu)函數(shù)的調(diào)用次序與構(gòu)造函數(shù)相反。P224例7-6派生類的構(gòu)造、析構(gòu)函數(shù)第37頁/共62頁39例7-6派生類析構(gòu)函數(shù)舉例派生類的構(gòu)造、析構(gòu)函數(shù)#include<iostream>usingnamespacestd;classB1 //基類B1聲明{public: B1(inti){cout<<"constructingB1"<<i<<endl;}

~B1(){cout<<"destructingB1"<<endl;}};classB2 //基類B2聲明{public: B2(intj){cout<<"constructingB2"<<j<<endl;}

~B2(){cout<<"destructingB2"<<endl;}

};classB3 //基類B3聲明{public: B3(){cout<<"constructingB3*"<<endl;}

~B3(){cout<<"destructingB3"<<endl;}

};第38頁/共62頁40classC:publicB2,publicB1,publicB3 {public: C(inta,intb,intc,intd):B1(a),memberB2(d),memberB1(c),B2(b){}private: B1memberB1; B2memberB2; B3memberB3;};voidmain(){ Cobj(1,2,3,4);}第39頁/共62頁41例7-6運(yùn)行結(jié)果constructingB22constructingB11constructingB3*constructingB13constructingB24constructingB3*destructingB3destructingB2destructingB1destructingB3destructingB1destructingB2第40頁/共62頁42同名隱藏規(guī)則當(dāng)派生類與基類中有相同成員時:若未強(qiáng)行指名,則通過派生類對象使用的是派生類中的同名成員。如果派生類中聲明了與基類成員函數(shù)同名的新函數(shù),即使函數(shù)的參數(shù)表不同,從基類繼承的同名函數(shù)的所有重載形式也都會被隱藏。如果某派生類的多個基類擁有同名的成員,同時,派生類又新增這樣的同名成員,派生類成員將隱藏所有基類的同名成員。如要通過派生類對象訪問基類中被覆蓋的同名成員,應(yīng)使用基類名限定。派生類成員的標(biāo)識與訪問第41頁/共62頁43例7-7多繼承同名隱藏舉例派生類成員的標(biāo)識與訪問#include<iostream>usingnamespacestd;classB1 {public: intnV; voidfun(){cout<<"MemberofB1"<<nV<<endl;}};classB2 {public: intnV; voidfun(){cout<<"MemberofB2"<<nV<<endl;}};第42頁/共62頁44classD1:publicB1,publicB2 {public: intnV; voidfun(){cout<<"MemberofD1"<<nV<<endl;}};voidmain(){ D1d1;

d1.nV=1;//對象名.成員名標(biāo)識,訪問D1類成員

d1.fun();

d1.B1::nV=2;//作用域分辨符標(biāo)識,訪問基類B1成員

d1.B1::fun();

d1.B2::nV=3;//作用域分辨符標(biāo)識,訪問基類B2成員

d1.B2::fun(); }派生類成員的標(biāo)識與訪問第43頁/共62頁45二義性問題舉例(一)classA{public:voidf();};classB{public:voidf();voidg()};classC:publicA,publicB{public:voidg();voidh();};如果聲明:Cc1;則c1.f();具有二義性而c1.g();無二義性

(同名覆蓋)派生類成員的標(biāo)識與訪問第44頁/共62頁46二義性的解決方法解決方法一:用類名來限定

c1.A::f()或c1.B::f()解決方法二:同名覆蓋

在C中聲明一個同名成員函數(shù)f(),f()再根據(jù)需要調(diào)用A::f()或B::f()派生類成員的標(biāo)識與訪問第45頁/共62頁47二義性問題舉例(二)classB{public:intb;};classB1:publicB{private:intb1;};classB2:publicB{private:intb2;};classC:publicB1,publicB2{public:intf();private:intd;};派生類成員的標(biāo)識與訪問第46頁/共62頁派生類C的對象的存儲結(jié)構(gòu)示意圖:bb1bb2dB類成員B類成員B1類成員B2類成員C類對象有二義性:Cc;c.bc.B::b無二義性:c.B1::bc.B2::b派生類成員的標(biāo)識與訪問第47頁/共62頁49二義性問題在多繼承時,基類與派生類之間,或基類之間出現(xiàn)同名成員時,將出現(xiàn)訪問時的二義性(不確定性)。當(dāng)派生類從多個基類派生,而這些基類又從同一個基類派生,則在訪問此共同基類中的成員時,將產(chǎn)生二義性。派生類成員的標(biāo)識與訪問第48頁/共62頁50虛基類虛基類的引入用于有共同基類的場合聲明以virtual修飾說明基類

例:classB1:virtualpublicB作用主要用來解決多繼承時可能發(fā)生的對同一基類繼承多次而產(chǎn)生的二義性問題。為最遠(yuǎn)的派生類提供惟一的基類成員,而不重復(fù)產(chǎn)生多次拷貝。注意在第一級繼承時就要將共同基類設(shè)計為虛基類。

虛基類第49頁/共62頁51虛基類舉例classB{public:intb;};classB1:virtualpublicB{private:intb1;};classB2:virtualpublicB{private:intb2;};classC:publicB1,publicB2{private:floatd;}下面的訪問是正確的:Ccobj;cobj.b;

虛基類第50頁/共62頁虛基類的派生類對象存儲結(jié)構(gòu)示意圖:BB1B2Cb1b2dB1類成員B2類成員C類對象bB類成員

虛基類第51頁/共62頁53例7-8虛基類舉例

虛基類D1nV:intnVd:intB1::nV1:intB2::nV2:intfund():voidfun():voidB1nV1:intB2nV2:intD1nVd:intfund():void<<virtual>>B0nV:intfun()第52頁/共62頁54B0B1新增成員B0B2新增成員D1新增成員B0B0B1B2D1nV,fun()

虛基類第53頁/共62頁55#include<iostream>usingnamespacestd;classB0 {public: intnV; voidfun(){cout<<"MemberofB0"<<endl;}};classB1:virtualpublicB0{public: intnV1;};classB2:virtualpublicB0{public: intnV2;};

虛基類第54頁/共62頁56classD1:publicB1,publicB2 {public: //新增外部接口

intnVd; voidfund(){cout<<"MemberofD1"<<endl;}};voidmain() {D1d1; //聲明D1類對象d1 d1.nV=2; d1.fun();}

虛基類第55頁/共62頁57虛基類及其派生類構(gòu)造函數(shù)建立對象時所指定的類稱為最(遠(yuǎn))派生類。虛基類的成員是由最遠(yuǎn)派生類的構(gòu)造函數(shù)通過調(diào)用虛基類的構(gòu)造函數(shù)進(jìn)行初始化的

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論