版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第10章繼承、多態(tài)和虛函數(shù)皮德常南京航空航天大學(xué)計算機科學(xué)與技術(shù)學(xué)院110.1繼承繼承是OOP程序設(shè)計中很重要的一個方面。繼承易于擴充現(xiàn)有類以滿足新的應(yīng)用。將已有的類稱之為父類,也稱基類,將新產(chǎn)生的類稱為子類,也稱為導(dǎo)出類或派生類。導(dǎo)出類不做任何改變地繼承了基類中的所有變量和函數(shù)〔構(gòu)造函數(shù)和析構(gòu)函數(shù)除外〕,并且還可以增加新的數(shù)據(jù)成員和函數(shù),從而使導(dǎo)出類比基類更為特殊化。Example:例10-1.2//Contentsofgrade.hclassGrade{ charletter; floatscore; voidcalcGrade();public: voidsetScore(floats){score=s;calcGrade();} floatgetScore(){returnscore;} chargetLetter(){returnletter;}};3//Contentsofgrade.cpp
#include"grade.h"http://DefinitionofmemberfunctionGrade::calcGradevoidGrade::calcGrade(){ if(score>89) letter='A'; elseif(score>79)letter='B'; elseif(score>69)letter='C'; elseif(score>59)letter='D'; elseletter='F';}4//Contentsoftest.h#include"grade.h"classTest:
publicGrade{ int numQuestions; float pointsEach; int numMissed;public: Test(int,int);};5//Contentsoftest.cpp#include"test.h"http://參數(shù)q代表問題的個數(shù),m代表答錯的題數(shù).Test::Test(intq,intm){ floatnumericGrade; numQuestions=q; numMissed=m; pointsEach=100.0f/numQuestions; numericGrade=100.0f-numMissed*pointsEach;
setScore(numericGrade);}6#include"test.h"voidmain(){ intquestions,missed; cout<<"Howmanyquestions?"; cin>>questions; cout<<"Howmanyquestionsmissed?"; cin>>missed; Testexam(questions,missed); cout.precision(2); cout<<"\nThescoreis"<<exam.getScore(); cout<<"\nThegradeis"<<exam.getLetter();}grade.hgrade.cpptest.htest.cpp10-1.cpp7上例中,父類中的公有成員在子類中仍是公有的,它們可以和子類中的公有成員一樣被訪問。但反過來是錯誤的,基類對象或基類中的某個函數(shù)不能調(diào)用子類中的函數(shù)。classBadBase{ intx;public: BadBase(){x=getVal();}//Error};classDerived:publicBadBase{ inty;public: Derived(intz){y=z;} intgetVal(){returny;}};810.2保護(hù)成員和類的訪問基類中的保護(hù)成員和私有成員比較類似,唯一的區(qū)別是:子類不可訪問基類中的私有成員,但可訪問基類中的保護(hù)成員。在公有繼承或保護(hù)繼承的情況下,子類能訪問基類的protected成員。Example:例10-29//Contentsofgrade2.hclassGrade{protected:
charletter; floatscore; voidcalcGrade();public: voidsetScore(floats){score=s;calcGrade();} floatgetScore(){returnscore;} chargetLetter(){returnletter;}};10//Contentsoftest2.h#include"grade2.h"classTest:publicGrade{ int numQuestions; float pointsEach; int numMissed;public: Test(int,int);
voidadjustScore();//新增加的函數(shù)};11//Contentsoftest2.cpp#include"test2.h"http://構(gòu)造函數(shù)略voidTest::adjustScore(){ if((score-int(score))>=0.5f){ score+=0.5; calcGrade(); }}who12繼承方式基類成員在子類中的表現(xiàn)private1.基類的私有成員在子類中不可訪問;2.基類的保護(hù)成員變成了子類中的私有成員;3.基類的公有成員變成了子類中的私有成員。protected1.基類的私有成員在子類中不可訪問;2.基類的保護(hù)成員變成了子類中的保護(hù)成員;3.基類的公有成員變成了子類中的保護(hù)成員。public1.基類的私有成員在子類中不可訪問;2.基類的保護(hù)成員變成了子類中的保護(hù)成員;3.基類的公有成員變成了子類中的公有成員。13private:xprotected:ypublic:zprivate:xprotected:ypublic:zprivate:xprotected:ypublic:zxisinaccessibleprivate:yprivate:zxisinaccessibleprotected:yprotected:zxisinaccessibleprotected:ypublic:zprivatebaseclassprotectedbaseclasspublicbaseclassExample:14注意如果省略了繼承修飾符,那么就是私有繼承: classTest:Grade不要將繼承修飾符與成員的訪問修飾符相混淆:成員訪問修飾符是規(guī)定類外語句能否訪問類中的成員,而繼承修飾符是為了限定基類成員在子類中的表現(xiàn)。1510.3構(gòu)造函數(shù)和析構(gòu)函數(shù)當(dāng)基類和子類都有構(gòu)造函數(shù)時,如果定義一個子類對象,那么首先要調(diào)用基類的構(gòu)造函數(shù),然后再調(diào)用子類的構(gòu)造函數(shù);析構(gòu)函數(shù)的調(diào)用次序與此相反,即先調(diào)用子類的析構(gòu)函數(shù),然后再調(diào)用基類的析構(gòu)函數(shù)。Example:
例10-3.16classBaseDemo{public: BaseDemo() {cout<<"InBaseDemoconstructor.\n";} ~BaseDemo() {cout<<"InBaseDemodestructor.\n";}};classDerivedDemo:publicBaseDemo{public: DerivedDemo() {cout<<"InDerivedDemoconstructor.\n";} ~DerivedDemo() {cout<<"InDerivedDemodestructor.\n";}};17voidmain(){ cout<<"下面定義一個DerivedDemo類對象\n"; DerivedDemoobject;
cout<<"下面將要結(jié)束程序
\n";}10-3.cpp1810.3.2向基類的構(gòu)造函數(shù)傳參數(shù)如果基類和子類都有缺省的構(gòu)造函數(shù),它們的調(diào)用是自動完成的,這是一種隱式調(diào)用。如果基類的構(gòu)造函數(shù)帶有參數(shù),那么必須讓子類的構(gòu)造函數(shù)顯式調(diào)用基類的構(gòu)造函數(shù),并且向基類構(gòu)造函數(shù)傳遞適當(dāng)?shù)膮?shù)。例10-419classRectangle{protected: floatwidth,length,area;public: Rectangle(){width=length=area=0.0f;}
Rectangle(floatw,floatl)
{ width=w;length=l; area=width*length; } floatgetArea(){returnarea;} floatgetLen(){returnlength;} floatgetWidth(){returnwidth;}};20classCube:publicRectangle{protected: floatheight,volume;public:
Cube(float,float,float); floatgetHeight(){returnheight;} floatgetVol(){returnvolume;}};Cube::Cube(floatw,floatl,floath):Rectangle(w,l){ height=h;volume=area*height;}Rectangle.hRectangle.cppCube.hCube.cpp10-4.cpp21Note如果基類沒有缺省的構(gòu)造函數(shù),那么子類必須至少具有一個帶參的構(gòu)造函數(shù),以便向基類構(gòu)造函數(shù)傳遞參數(shù)。2210.3.3初始化列表的作用1.
如果類之間具有繼承關(guān)系,子類必須在其初始化列表中調(diào)用基類的構(gòu)造函數(shù)。例:classBase{ Base(intx);}; classDerived:publicBase{ Derived(intx,inty):Base(x)
{ /*…*/} };2310.3.3初始化列表的作用2.
類中的const常量只能在初始化列表中進(jìn)行初始化,而不能在函數(shù)體內(nèi)用賦值的方式來初始化。classBase{
constintSIZE;
Base(intsize):SIZE(size)
{/*…*/}};Baseone(100);2410.3.3初始化列表的作用3.對象類型的成員的初始化放在初始化列表中,那么效率較高,反之較低。根本類型變量的初始化可以在初始化列表中,也可在構(gòu)造函數(shù)中,效率上沒區(qū)別。classBase{Base();Base(constBase&other);};classDerived{BaseB_Member;public:Derived(constBase&a);};構(gòu)造函數(shù)的實現(xiàn):Derived::Derived(constBase&b):B_Member(b){/*…*/}也可這樣實現(xiàn),但效率較低。Derived::Derived(constBase&b){B_Member=b;}2510.4覆蓋基類的函數(shù)成員重載的特點:(1)重載表現(xiàn)為有多個函數(shù),它們的名字相同,但參數(shù)不全相同;(2)重載可以出現(xiàn)在同一個類中,也可出現(xiàn)在具有繼承關(guān)系的父類與子類中;(3)重載也可表現(xiàn)為外部函數(shù)的形式。2610.4覆蓋基類的函數(shù)成員覆蓋的特點:(1)覆蓋一定出現(xiàn)在具有繼承關(guān)系的基類和子類之間;(2)覆蓋除了要求函數(shù)名完全相同,還要求相應(yīng)的參數(shù)個數(shù)和類型也完全相同;(3)當(dāng)進(jìn)行函數(shù)調(diào)用時,子類對象所調(diào)用的是子類中定義的函數(shù);(4)覆蓋是C++多態(tài)性的局部表達(dá)。27classMileDist{protected:floatmiles;public: voidsetDist(floatd){miles=d;} floatgetDist(){returnmiles;}};classFeetDist:publicMileDist{ protected:floatfeet;public: voidsetDist(float); floatgetDist(){returnfeet;} floatgetMiles(){returnmiles;}};28voidFeetDist::setDist(floatft){ feet=ft;
MileDist::setDist(feet/5280);//Callbaseclassfunction}voidmain(){FeetDistfeet;floatft;cout<<"Adistanceinfeetandconvertittomiles:";cin>>ft;feet.setDist(ft);cout<<feet.getDist()<<"feetequals";cout<<feet.getMiles()<<"miles.\n";}哪一個?MileDist.hFeetDist.hFeetDist.cpp10-5.cpp2910.5虛函數(shù)函數(shù)覆蓋表達(dá)了一定的多態(tài)性。但是,簡單的函數(shù)覆蓋并不能稱為真正的多態(tài)性。Example:例10-730classMileDist{protected: floatmiles;public: voidsetDist(floatd){miles=d;} floatgetDist(){returnmiles;} floatsquare(){returngetDist()*getDist();}};who31classFeetDist:publicMileDist{protected: floatfeet;public: voidsetDist(float); floatgetDist(){returnfeet;} floatgetMiles(){returnmiles;}};voidFeetDist::setDist(floatft){ feet=ft; MileDist::setDist(feet/5280);}32voidmain(){ FeetDistfeet; floatft; cout<<"請輸入以英尺為單位的距離:"; cin>>ft; feet.setDist(ft); cout<<feet.getDist()<<"英尺等于"; cout<<feet.getMiles()<<"英里\n"; cout<<feet.getDist()<<"平方等于"; cout<<feet.square()<<"\n";}MileDist2.hFeetDist2.hFeetDist2.cpp10-7.cpp33錯誤的原因:C++編譯器在缺省情況下,對函數(shù)成員的調(diào)用實施的是靜態(tài)連編〔也稱靜態(tài)綁定〕。解決方法:將getDist設(shè)置為虛函數(shù)。對于虛函數(shù),編譯器完成的是動態(tài)連編〔也稱動態(tài)綁定〕,即對函數(shù)的調(diào)用是在運行時確定的。OOP:覆蓋和重載不能表達(dá)真正的多態(tài)性,只有虛函數(shù)才是多態(tài)性的表現(xiàn)。不支持多態(tài)性的語言,就不能稱為OOP。3410.6純虛函數(shù)和抽象類純虛函數(shù)是在基類中聲明的虛函數(shù),沒有函數(shù)體,要求繼承基類的子類必須覆蓋它。帶有純虛函數(shù)的類稱為抽象類,不能定義抽象類的對象。派生類可以根據(jù)自己的需要,分別覆蓋它,從而實現(xiàn)真正意義上的多態(tài)性。格式:virtualvoidshowInfo()=0;35classStudent//例10-9{protected: charname[51]; inthours;public: Student(){name[0]=hours=0; } voidsetName(char*n){strcpy(name,n);} //Purevirtualfunction
virtualvoidsetHours()=0; virtualvoidshowInfo()=0;};36classCsStudent:publicStudent{ intmathHours,csHours;public: voidsetMathHours(intmh){mathHours=mh;} voidsetCsHours(intcsh){csHours=csh;} voidsetHours() { hours=mathHours+csHours; } voidshowInfo();};37voidCsStudent::showInfo(){ cout<<"Name:"<<name<<endl; cout<<"\tMath:"<<mathHours<<endl; cout<<"\tCS:"<<csHours; cout<<"\n\tTotalHours:"<<hours;}voidmain(){ CsStudentstudent1; charchInput[51]; intintInput;38 cout<<"Enterthefollowinginformation:\n"; cout<<"Name:"; cin.getline(chInput,51); student1.setName(chInput); cout<<"Numberofmathhourscompleted:"; cin>>intInput; student1.setMathHours(intInput); cout<<"NumberofCShourscompleted:"; cin>>intInput; student1.setCsHours(intInput); student1.setHours(); cout<<"\nSTUDENTINFORMATION\n"; student1.showInfo();}Student.hCsStudent.hCsStudent.cpp10-9.cpp39關(guān)于抽象類和純虛函數(shù)小節(jié)如果一個類包含有純虛函數(shù),那么它就是抽象類,必須讓其它類繼承;基類中的純虛函數(shù)沒有代碼;不能定義抽象類的對象,即抽象基類不能實例化;必須在子類中覆蓋基類中的純虛函數(shù)。4010.6.3指向基類的指針指向基類對象的指針可以指向其子類的對象;如果子類覆蓋了基類中的成員,但通過基類指針?biāo)L問的成員仍是基類的成員,而不是子類成員。Example:例10-1041classBase{public:
voidshow(){cout<<"InBaseclass.\n";}};classDerived:publicBase{public:
voidshow(){cout<<"InDerivedclass.\n";}};voidmain(){ Base*bptr; Deriveddobject; bptr=&dobject; bptr->show();}10-10.cpp1.調(diào)用誰?2.什么原因?3.如何解決?4.引用調(diào)用呢?4210.7多重繼承classAclassBclassCClassCinheritsallofClassB'smembers,includingtheonesClassBinheritedfromClassA.4310.8多繼承如果一個子類具有兩個或多個直接父類,那么就稱為多繼承。classAclassBclassCConstructorsarecalledintheordertheyarelistedinthefirstlineoftheclassdeclaration.44classDate //例10-12
{protected: intday,month,year;public: Date(intd,intm,inty) { day=d;month=m;year=y; } intgetDay(){returnday;} intgetMonth(){returnmonth;} intgetYear(){returnyear;}};45classTime{protected: inthour,min,sec;public: Time(inth,intm,ints) { hour=h;min=m;sec=s; } intgetHour(){returnhour;} intgetMin(){returnmin;} intgetSec(){returnsec;}};46classDateTime:publicDate,publicTime
{protected: chardTString[20];public:
DateTime(int,int,int,int,int,int); voidgetDateTime(char*str) { strcpy(str,dTString); }};這個順序很重要47DateTime::DateTime(intyr,intmon,intdy,inthr,intmt,intsc):Time(hr,mt,sc),Date(dy,mon,yr)
{ chartemp[10];//IntheformYY/MM/DD strcpy(dTString,itoa(getYear(),temp,10)); strcat(dTString,"/"); strcat(dTString,itoa(getMonth(),temp,10)); strcat(dTString,"/"); strcat(dTString,itoa(getDay(),temp,10)); strcat(dTString,""); strcat(dTString,itoa(getHour(),temp,10)); strcat(dTString,":"); strcat(dTString,itoa(getMin(),temp,10)); strcat(dTString,":"); strcat(dTString,itoa(getSec(),temp,10));}48voidmain(){ charformatted[20]; DateTimepastDay(28,7,2010,11,32,27); pastDay.getDateTime(formatted); cout<<formatted<<endl;}Time.hDate.hDateTime.h
DateTime.cpp10-12.cpp49#include<ctime>#include<iostream>usingnamespacestd;voidmain(){chartmpbuf[128];//Displayoperatingsystem-styledateandtime_strtime(tmpbuf);cout<<"time:\t"<<tmpbuf<<endl;_strdate(tmpbuf);cout<<"date:\t"<<tmpbuf<<endl;}獲取系統(tǒng)時間Ex10-a.cpp5010.9類模板類模板用于創(chuàng)立類屬類和抽象數(shù)據(jù)類型,從而使程序員可以創(chuàng)立一般形式的類,而不必編寫處理不同數(shù)據(jù)類型的類。類模板的定義和實現(xiàn)必須在同一個文件中,通常是頭文件。編譯器看到模板實現(xiàn)時才展開模板。Example:Program10-13.51template<classT>classFreewillArray{ T*aptr; intarraySize; voidmemError(void); //allocationerrors
voidsubError(void); //outofrangepublic: FreewillArray(){aptr=0;arraySize=0;} FreewillArray(int); FreewillArray(constFreewillArray&); ~FreewillArray(); intsize() {returnarraySize;}
T&operator[](constint&);};52//ConstructorforFreewillArrayclass.
template<classT>FreewillArray<T>::FreewillArray(ints){ arraySize=s; aptr=newT[s]
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 電氣課程設(shè)計報告論文
- 零售貸款合同三篇
- 道路工程師工作總結(jié)
- 婦產(chǎn)科護(hù)士工作總結(jié)
- 門診部醫(yī)生團(tuán)隊近期工作總結(jié)
- 2023-2024學(xué)年重慶市七校聯(lián)盟高一(下)期中語文試卷
- 教材選用與內(nèi)容審定計劃
- 包裝設(shè)計師的主要職責(zé)
- 醫(yī)療行業(yè)顧問工作概述
- 【八年級下冊地理粵教版】7.4 北京市 同步練習(xí)
- 酒店員工培訓(xùn)方案(3篇)
- 2024版光伏發(fā)電項目承包經(jīng)營權(quán)轉(zhuǎn)讓合同范本3篇
- 2024年協(xié)會工作計劃范例(2篇)
- 內(nèi)蒙古自治區(qū)赤峰市2024-2025學(xué)年高三上學(xué)期11月期中物理試題(解析版)
- 廣州廣東廣州市海珠區(qū)瑞寶街招聘雇員9人筆試歷年參考題庫頻考點試題附帶答案詳解
- 國家開放大學(xué)電大臨床藥理學(xué)形考任務(wù)1-3參考答案
- 2024年人教版七年級下冊英語期末綜合檢測試卷及答案
- 2025年高中政治學(xué)業(yè)水平考試時政考點歸納總結(jié)(復(fù)習(xí)必背)
- 統(tǒng)編版(2024新版)七年級下冊道德與法治期末復(fù)習(xí)背誦知識點提綱
- 房屋市政工程生產(chǎn)安全重大事故隱患判定標(biāo)準(zhǔn)(2024版)宣傳畫冊
- 老舊小區(qū)改造工程安全管理體系管理制度及措施
評論
0/150
提交評論