




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第10章繼承、多態(tài)和虛函數(shù)皮德常南京航空航天大學計算機科學與技術學院110.1繼承繼承是OOP程序設計中很重要的一個方面。繼承易于擴充現(xiàn)有類以滿足新的應用。將已有的類稱之為父類,也稱基類,將新產生的類稱為子類,也稱為導出類或派生類。導出類不做任何改變地繼承了基類中的所有變量和函數(shù)〔構造函數(shù)和析構函數(shù)除外〕,并且還可以增加新的數(shù)據成員和函數(shù),從而使導出類比基類更為特殊化。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ù)不能調用子類中的函數(shù)。classBadBase{ intx;public: BadBase(){x=getVal();}//Error};classDerived:publicBadBase{ inty;public: Derived(intz){y=z;} intgetVal(){returny;}};810.2保護成員和類的訪問基類中的保護成員和私有成員比較類似,唯一的區(qū)別是:子類不可訪問基類中的私有成員,但可訪問基類中的保護成員。在公有繼承或保護繼承的情況下,子類能訪問基類的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://構造函數(shù)略voidTest::adjustScore(){ if((score-int(score))>=0.5f){ score+=0.5; calcGrade(); }}who12繼承方式基類成員在子類中的表現(xiàn)private1.基類的私有成員在子類中不可訪問;2.基類的保護成員變成了子類中的私有成員;3.基類的公有成員變成了子類中的私有成員。protected1.基類的私有成員在子類中不可訪問;2.基類的保護成員變成了子類中的保護成員;3.基類的公有成員變成了子類中的保護成員。public1.基類的私有成員在子類中不可訪問;2.基類的保護成員變成了子類中的保護成員;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構造函數(shù)和析構函數(shù)當基類和子類都有構造函數(shù)時,如果定義一個子類對象,那么首先要調用基類的構造函數(shù),然后再調用子類的構造函數(shù);析構函數(shù)的調用次序與此相反,即先調用子類的析構函數(shù),然后再調用基類的析構函數(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<<"下面將要結束程序
\n";}10-3.cpp1810.3.2向基類的構造函數(shù)傳參數(shù)如果基類和子類都有缺省的構造函數(shù),它們的調用是自動完成的,這是一種隱式調用。如果基類的構造函數(shù)帶有參數(shù),那么必須讓子類的構造函數(shù)顯式調用基類的構造函數(shù),并且向基類構造函數(shù)傳遞適當?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如果基類沒有缺省的構造函數(shù),那么子類必須至少具有一個帶參的構造函數(shù),以便向基類構造函數(shù)傳遞參數(shù)。2210.3.3初始化列表的作用1.
如果類之間具有繼承關系,子類必須在其初始化列表中調用基類的構造函數(shù)。例:classBase{ Base(intx);}; classDerived:publicBase{ Derived(intx,inty):Base(x)
{ /*…*/} };2310.3.3初始化列表的作用2.
類中的const常量只能在初始化列表中進行初始化,而不能在函數(shù)體內用賦值的方式來初始化。classBase{
constintSIZE;
Base(intsize):SIZE(size)
{/*…*/}};Baseone(100);2410.3.3初始化列表的作用3.對象類型的成員的初始化放在初始化列表中,那么效率較高,反之較低。根本類型變量的初始化可以在初始化列表中,也可在構造函數(shù)中,效率上沒區(qū)別。classBase{Base();Base(constBase&other);};classDerived{BaseB_Member;public:Derived(constBase&a);};構造函數(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)在具有繼承關系的父類與子類中;(3)重載也可表現(xiàn)為外部函數(shù)的形式。2610.4覆蓋基類的函數(shù)成員覆蓋的特點:(1)覆蓋一定出現(xiàn)在具有繼承關系的基類和子類之間;(2)覆蓋除了要求函數(shù)名完全相同,還要求相應的參數(shù)個數(shù)和類型也完全相同;(3)當進行函數(shù)調用時,子類對象所調用的是子類中定義的函數(shù);(4)覆蓋是C++多態(tài)性的局部表達。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ù)覆蓋表達了一定的多態(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ù)成員的調用實施的是靜態(tài)連編〔也稱靜態(tài)綁定〕。解決方法:將getDist設置為虛函數(shù)。對于虛函數(shù),編譯器完成的是動態(tài)連編〔也稱動態(tài)綁定〕,即對函數(shù)的調用是在運行時確定的。OOP:覆蓋和重載不能表達真正的多態(tài)性,只有虛函數(shù)才是多態(tài)性的表現(xiàn)。不支持多態(tài)性的語言,就不能稱為OOP。3410.6純虛函數(shù)和抽象類純虛函數(shù)是在基類中聲明的虛函數(shù),沒有函數(shù)體,要求繼承基類的子類必須覆蓋它。帶有純虛函數(shù)的類稱為抽象類,不能定義抽象類的對象。派生類可以根據自己的需要,分別覆蓋它,從而實現(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關于抽象類和純虛函數(shù)小節(jié)如果一個類包含有純虛函數(shù),那么它就是抽象類,必須讓其它類繼承;基類中的純虛函數(shù)沒有代碼;不能定義抽象類的對象,即抽象基類不能實例化;必須在子類中覆蓋基類中的純虛函數(shù)。4010.6.3指向基類的指針指向基類對象的指針可以指向其子類的對象;如果子類覆蓋了基類中的成員,但通過基類指針所訪問的成員仍是基類的成員,而不是子類成員。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.調用誰?2.什么原因?3.如何解決?4.引用調用呢?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ù)據類型,從而使程序員可以創(chuàng)立一般形式的類,而不必編寫處理不同數(shù)據類型的類。類模板的定義和實現(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)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 汕頭大學《計算機技術與應用》2023-2024學年第二學期期末試卷
- 西安體育學院《商務筆譯》2023-2024學年第二學期期末試卷
- 安徽衛(wèi)生健康職業(yè)學院《服飾圖案設計》2023-2024學年第二學期期末試卷
- 西京學院《臨床基本技能學2》2023-2024學年第二學期期末試卷
- 上海立信會計金融學院《能源電力電子技術》2023-2024學年第二學期期末試卷
- 蘭考三農職業(yè)學院《商務英語筆譯》2023-2024學年第二學期期末試卷
- 黑龍江財經學院《公共管理倫理學》2023-2024學年第二學期期末試卷
- 南寧學院《航空維修工程學》2023-2024學年第二學期期末試卷
- 河北水利電力學院《工科化學2(全英文)》2023-2024學年第二學期期末試卷
- 武漢華夏理工學院《照相寫實繪畫》2023-2024學年第二學期期末試卷
- 活性炭濾池的設計計算
- JGT334-2012 建筑外墻用鋁蜂窩復合板
- 個體防護裝備PPE重要性課件
- 圖紙會審記錄表格
- 量子力學主要知識點復習資料
- 如何編制過程流程圖、PFMEA、控制計劃文件
- 湖南省2023年跨地區(qū)普通高等學校對口招生第一次聯(lián)考(語文對口)參考答案
- 液化石油氣充裝操作規(guī)程
- 初中《道德與法治》課堂有效教學的建構、實施與創(chuàng)新
- 供應鏈公司成立方案
- 質量風險與機遇分析評價表完整
評論
0/150
提交評論