版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
主講:嚴冬梅第6章繼承和多態(tài)(Inheritance&Polymorphism)面向?qū)ο蟪绦蛟O(shè)計(C++)OrientedObjectProgramming(C++)面向?qū)ο蟮奶卣鞒橄螅ˋbstraction)封裝(Encapsulation)繼承(Inheritance)多態(tài)(Polymorphism)第6章繼承和多態(tài)繼承是C++語言的一種重要機制,該機制自動地為一個類提供來自另一個類的操作和數(shù)據(jù)結(jié)構(gòu),這使得程序員只需在新類中定義已有類中沒有的成分來建立新類。第6章繼承和多態(tài)
6.1繼承
6.2多態(tài)性
6.3抽象類6.1繼承
6.1.1
繼承的概念繼承就是從父輩處得到屬性和行為特征。類的繼承是新的類從已有類那里得到已有類的特征。原有的類稱為基類或父類,產(chǎn)生的新類稱為派生類或子類。繼承就是創(chuàng)建一個具有別的類的屬性和行為的新類的能力。繼承幫助我們描述事物的層次關(guān)系,使得我們用一種簡單的方式來描述事物。繼承支持軟件復用,縮短軟件開發(fā)時間,提高效率6.1繼承交通工具分類層次圖交通工具火車汽車飛機輪船卡車旅行車小汽車工具車轎車面包車基類/父類“is-a”關(guān)系6.1繼承6.1.1
繼承的概念繼承的實質(zhì)就是構(gòu)造新的派生類。派生類(也稱子類)繼承它父類的屬性和操作子類也聲明了新的屬性和新的操作剔除了那些不適合于其用途的繼承下來的操作。這樣,繼承可讓你重用父類的代碼,專注于為子類編寫新代碼。6.1繼承6.1.2派生類的構(gòu)造格式class
派生類名:繼承方式1基類名1,繼承方式2基類名2……{……};
派生類不繼承的特殊函數(shù)構(gòu)造函數(shù)(C++11已允許)析構(gòu)函數(shù)作為特權(quán)地位的友元函數(shù)
賦值運算符函數(shù)classA{public:A(inti){}};classB:publicA{public:
usingA::A;};6.1繼承6.1.2派生類的構(gòu)造派生類的生成過程吸收基類成員(成員函數(shù)與屬性)改造基類成員(只能重新定義成員函數(shù))添加新的成員(成員函數(shù)與屬性)
派生類構(gòu)造開始時,仍然是先調(diào)用基類的構(gòu)造函數(shù)6.1繼承
6.1.2派生類的構(gòu)造派生類可以直接訪問基類的保護數(shù)據(jù)成員,但是一般不這么做,而是通過基類的接口(成員函數(shù))去訪問他們。好處是一旦基類的實現(xiàn)有錯誤,只要不涉及接口,那么基類的修改不會影響派生類的操作。6.1繼承classA{protected:
inta;public:
voidsetA(intx){a=x;}};classB:publicA{intb;public:Set(intx,inty){a=x;b=y;}};classA{protected:
inta;public:voidsetA(intx){a=x;}};classB:publicA{
intb;public:Set(intx,inty){setA(x);b=y;}};6.1繼承classstudent{……private:
charname[10];
floataverage;};classGraduateStudent:publicstudent{……private:
intqualifierGrade;};從Student繼承部分(14字節(jié))GraduateStudent特有部分(4字節(jié))thisGraduateStudent對象(共18字節(jié))6.1繼承6.1.2派生類的構(gòu)造派生類構(gòu)造函數(shù)可直接調(diào)用基類構(gòu)造函數(shù)
BaseClass(formalList){}DerivedClass(parameterList):BaseClass(actualList){}BaseClass(){}DerivedClass(parameterList):BaseClass()//可缺省{}
6.1繼承#include<iostream>#include<string>usingnamespacestd;classStudent{public:Student(conststringpName="Noname"){name=pName;average=semesterHours=0;cout<<"Constructingastudent."<<name<<endl;}protected:stringname;
intsemesterHours;floataverage;};【例6.1】派生類的構(gòu)造classGraduateStudent:publicStudent{public:GraduateStudent(constchar*pName="Noname"):Student(pName){qualiferGrade=0;cout<<"Constructingagraduatestudent."<<endl;}protected:
intqualiferGrade;};intmain(){GraduateStudentgs("Randy");
return0;}6.1繼承Constructingastudent.RandyConstructingagraduatestudent.6.1繼承6.1.2派生類的構(gòu)造若基類構(gòu)造函數(shù)未被顯示調(diào)用,基類的無參構(gòu)造函數(shù)就會被自動調(diào)用DerivedClass(parameterList){}
注意基類是否具有無參的構(gòu)造函數(shù)BaseClass(){}6.1繼承usingnamespacestd;classStudent{public:Student(conststringpName="Noname"){name=pName;average=semesterHours=0;cout<<"Constructingastudent."<<name<<endl;}protected:stringname;
intsemesterHours;floataverage;};【例6.2】基類的無參構(gòu)造函數(shù)被自動調(diào)用classGraduateStudent:publicStudent{public:GraduateStudent(){qualiferGrade=0;cout<<"Constructingagraduatestudent."<<endl;}protected:
intqualiferGrade;};intmain(){GraduateStudentgs;
return0;}6.1繼承Constructingastudent.NonameConstructingagraduatestudent.6.1繼承6.1.3繼承與組合類以另一類對象作數(shù)據(jù)成員,稱為組合intmain(){Carc;vehicleFun(c);//OKmotorFun(c);//ERRORmotorFun(c.motor);//OKreturn0;}classVehicle{……};classMotor{……};classCar:publicVehicle{public:Motormotor;};voidvehicleFun(Vehicle&v);voidmotorFun(Motor&m);6.1繼承usingnamespacestd;classAdvisor{intnoOfMeeting;public:Advisor(){cout<<"Constructinganadvisor."<<endl;}Advisor(Advisor&a){cout<<"Copyconstructinganadvisor."<<endl;}};classStudent{public:Student(stringpName="noname"){name=pName;average=semesterHours=0;cout<<"Constructingastudent.“<<endl;}protected:stringname;intsemesterHours;floataverage;};【例6.3】類的組合與繼承同時存在6.1繼承classGraduateStudent:publicStudent{public:GraduateStudent(stringpName,Advisor&adv)
:Student(pName),advisor(adv){qualiferGrade=0;cout<<"Constructingagraduatestudent."<<endl;}protected:Advisoradvisor;
intqualiferGrade;};voidfn(Advisor&advisor){GraduateStudentgs("Randy",advisor);}intmain(){Advisorda;fn(da);return0;}Constructinganadvisor.Constructingastudent.RandyCopyconstructinganadvisor.Constructingagraduatestudent.6.2多態(tài)性6.2.1
多態(tài)的概念
polymorphism來源于兩個希臘單詞,poly—“多”,morphos—“形態(tài)”。廣義的多態(tài):不同對象對于相同的消息有不同的響應
函數(shù)重載(至少有一個特征不同)
參數(shù)類型、參數(shù)數(shù)量、參數(shù)順序、const
函數(shù)重定義(函數(shù)特征相同)
同名、同參數(shù)、同返回值
在基類和派生類均定義#include<iostream>usingnamespacestd;classA{public:intf(){cout<<"f():"<<1<<endl;return1;}
intf(inti){cout<<"f(int):"<<i<<endl;returni+1;}};intmain(){Aa;a.f();a.f(5);return0;}函數(shù)重載f():1f(int):5intadd(intx,inty){returnx+y;}doubleadd(doublex,doubley){returnx+y;}【例6.4】類成員函數(shù)的重載#include<iostream>usingnamespacestd;classA{public:intf(){cout<<"A::f()"<<endl;return1;}};classB:publicA{public:
intf(){cout<<"B::f()"<<endl;return8;}};intmain(){Aa;Bb;cout<<a.f()<<endl;cout<<b.f()<<endl;cout<<b.A::f()<<endl;return0;}函數(shù)重定義A::f()1B::f()8A::f()1【例6.5】不同類有相同名字的成員函數(shù)6.2多態(tài)性6.2.1
多態(tài)的概念狹義的多態(tài):運行時能依據(jù)對象類型確認調(diào)用哪個函數(shù)的能力派生類重新定義基類的操作(除了返回值可以不同,其它完全相同)運行時的多態(tài)性—虛函數(shù)基類指針(引用)指向(引用)基類或派生類對象6.2多態(tài)性6.2.2
聯(lián)編(Binding)確定具有多態(tài)性的語句調(diào)用哪個函數(shù)的過程
靜態(tài)聯(lián)編(StaticBinding)
在程序編譯時確定調(diào)用哪個函數(shù)
例:函數(shù)重載、函數(shù)重定義
動態(tài)聯(lián)編(DynamicBinding)
在程序運行時,才能確定調(diào)用哪個函數(shù)
用動態(tài)聯(lián)編實現(xiàn)的多態(tài),也成為運行時多態(tài)(狹義多態(tài))#include<iostream>usingnamespacestd;classA{public:
virtual
voidf(){cout<<"A::f()“<<endl;}};classB:publicA{public:
voidf(){cout<<"B::f()"<<endl;}};voidfunc(A*p){p->f();}intmain(){Aa;Bb;func(&a);func(&b);return0;}6.2多態(tài)性6.2.2如何實現(xiàn)狹義多態(tài)在基類成員函數(shù)函數(shù)頭最前面加關(guān)鍵字virtualA::f()B::f()【例6.6】虛函數(shù)(基類指針)6.2多態(tài)性Callingtest(bc)InBaseclass
Callingtest(sc)
InSubClass#include<iostream>usingnamespacestd;classBase{public:
virtualvoidfn();
};
voidBase::fn(){cout<<"InBaseclass\n";}
classSubClass:publicBase
{public:virtualvoidfn();};
voidSubClass::fn(){cout<<"InSubClass\n";}voidtest(Base&b){b.fn();}
intmain()
{Basebc;SubClasssc;
cout<<"Callingtest(bc)\n";test(bc);
cout<<"Callingtest(sc)\n";test(sc);
return0;
}【例6.7】虛函數(shù)(基類引用)6.2多態(tài)性classShape{public:Shape(doublex,doubley):xCoord(x),yCoord(y){}
virtual
doubleArea()const{return0.0;}protected:
doublexCoord,yCoord;};classCircle:
publicShape{public:Circle(doublex,doubley,doubler):Shape(x,y),radius(r){}
virtualdoubleArea()const
{return3.14*radius*radius;}protected:
doubleradius;};【例6.8】繼承-矩形classRectangle:publicShape{public:Rectangle(doublex1,doubley1,doublex2,doubley2)
:Shape(x1,y1),x2Coord(x2),y2Coord(y2){}
virtualdoubleArea()const;protected:
doublex2Coord,y2Coord;};doubleRectangle::Area()const{returnfabs((xCoord-x2Coord)*(yCoord-y2Coord));}voidfun(constShape&sp){cout<<sp.Area()<<endl;}intmain(){
Circlec(2.0,5.0,4.0);fun(c);Rectanglet(2.0,4.0,1.0,2.0);fun(t);return0;}50.2426.2多態(tài)性6.2多態(tài)性6.2.3
多態(tài)的判定如果虛函數(shù)在基類與子類中出現(xiàn)的僅僅是名字的相同,而參數(shù)類型不同,或返回類型不同,即使寫上了virtual
關(guān)鍵字,則也不進行遲后聯(lián)編。classBase{public:
virtualvoidfn(intx){cout<<"InBaseclass,intx="<<x<<endl;}};classSubClass:publicBase{public:
virtualvoidfn(floatx)
{cout<<"InSubClass,floatx="<<x<<endl;}};voidtest(Base&b){inti=1;b.fn(i);floatf=2.5;b.fn(f);
}intmain(){Basebc;SubClasssc;cout<<"Callingtest(bc)\n";test(bc);cout<<"Callingtest(sc)\n";test(sc);sc.fn(2.5);return0;}6.2多態(tài)性6.2.3
多態(tài)的判定Callingtest(bc)InBaseclass,intx=1InBaseclass,intx=2Callingtest(sc)InBaseclass,intx=1InBaseclass,intx=2InSubClaseclass,floatx=2.5沒有形成多態(tài)父類virtualvoidfn(floatx)或子類virtualvoidfn(intx)【例6.9】未實現(xiàn)的多態(tài)classBase{public:
virtualBase*afn(){cout<<"ThisisBaseclass.\n";returnthis;}};classSubClass:publicBase{public:
SubClass*afn(){cout<<"ThisisSubClass.\n";returnthis;}};voidtest(Base&x){Base*b;b=x.afn();
}intmain(){Basebc;SubClasssc;
test(bc);test(sc);return0;}6.2多態(tài)性6.2.3
多態(tài)的判定ThisisBaseclassThisisSubClass.修改了Base類的虛函數(shù)afn()【例6.10】實質(zhì)的多態(tài)6.2多態(tài)性6.2.4虛函數(shù)的限制
一個類中將所有的成員函數(shù)都盡可能地設(shè)置為虛函數(shù)總是有益的。
注意:
只有類的成員函數(shù)才能說明為虛函數(shù)
靜態(tài)成員函數(shù)不能是虛函數(shù),因為靜態(tài)函數(shù)不受限于某個對象
內(nèi)聯(lián)函數(shù)不能是虛函數(shù)
構(gòu)造函數(shù)不能是虛函數(shù)
析構(gòu)函數(shù)可以是虛函數(shù),而且通常聲明為虛函數(shù)6.2多態(tài)性基類與派生類有同名函數(shù)時靜態(tài)聯(lián)編(函數(shù)重定義)通過派生類訪問同名函數(shù)通過基類對象的指針(引用)訪問同名函數(shù)動態(tài)聯(lián)編通過基類對象的指針(引用)訪問同名虛函數(shù)某類自己有同名函數(shù)靜態(tài)聯(lián)編(函數(shù)重載)6.2多態(tài)性6.2.5
類的分解
從相似的類中,將共有特征提取出來的過程稱為分解(factoring),分解使類的層次合理化和減少冗余6.3抽象類6.3.1
抽象類
C++允許程序員聲明一個不能有實例對象的類,這樣的類唯一的用途是被繼承,這種類稱為抽象類(abstractclass),一個抽象類至少具有一個純虛函數(shù),所謂純虛函數(shù)(purevirtualfunction)是指被標明為不具體實現(xiàn)的虛成員函數(shù)。6.3抽象類6.3.2
純虛函數(shù)的需要性不能創(chuàng)建一個抽象類的對象,但是可以聲明一個抽象類的指針或引用.voidfunc(Account*pA){pA->Withdrawal(100.0);}voidotherFunc(){Savingss;Checkingc;func(&s);//OK,一個Saving是一個Accountfunc(&c);//OK,一個Checkings是一個Account}6.3抽象類6.3.2
純虛函數(shù)的需要性如果在Account類里去掉Withdraw()純虛函數(shù),使得在其子類中分別分別添加Withdrawal()成員函數(shù)的定義,程序仍能通過編譯和連接,C++是強類型語言,當訪問一個成員函數(shù)時,C++堅持要證明該成員函數(shù)在類中存在,否則,拒絕接受,如果Withdrawal()是Account的成員函數(shù),即使是純虛函數(shù),也能順利通過編譯。純虛函數(shù)是在基類中為子類保留的一個位置,以便子類用自己的實在函數(shù)定義來重載之,如果在基類中沒有保留位置,則就沒有重載。6.3抽象類6.3.2
純虛函數(shù)的需要性不能創(chuàng)建一個抽象類的對象,但是可以聲明一個抽象類的指針或引用.
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 工作總結(jié)之風電實習總結(jié)
- 工作總結(jié)之動漫公司實習總結(jié)
- 銀行合規(guī)管理制度實施規(guī)劃
- 《保險代理機構(gòu)規(guī)定》課件
- 《政府透明度完美版》課件
- 《保安培訓教材》課件
- 教師師德演講范文(30篇)
- 探究熔化與凝固的特點課件粵教滬版
- 《信用保險培訓》課件
- 八年級英語Hasitarrivedyet課件
- 統(tǒng)編版(2024版)七年級上冊歷史期末復習課件
- 高校教師職稱答辯演講稿
- 2024-2025學年人教版七年級地理上學期地理知識點
- 國開2024年秋《機械制圖》形考作業(yè)1-4答案
- 計算機網(wǎng)絡智慧樹知到期末考試答案章節(jié)答案2024年上海電力大學
- 勞動教育智慧樹知到期末考試答案章節(jié)答案2024年溫州醫(yī)科大學
- MOOC 創(chuàng)業(yè)管理-江蘇大學 中國大學慕課答案
- 2024年四川省自然資源投資集團有限責任公司招聘筆試參考題庫附帶答案詳解
- 手機號碼歸屬地數(shù)據(jù)庫
- 北師大六年級數(shù)學上冊期末復習計劃
- 最新系統(tǒng)FMEA—(SFMEA)
評論
0/150
提交評論