版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第六章虛函數(shù)和多態(tài)性1第六章虛函數(shù)和多態(tài)性1目標理解靜態(tài)聯(lián)編和動態(tài)聯(lián)編的含義熟練掌握虛函數(shù)的使用掌握虛析構(gòu)函數(shù)的作用掌握抽象類掌握多態(tài)性2目標理解靜態(tài)聯(lián)編和動態(tài)聯(lián)編的含義26.1靜態(tài)聯(lián)編和動態(tài)聯(lián)編36.1靜態(tài)聯(lián)編和動態(tài)聯(lián)編36.1靜態(tài)聯(lián)編和動態(tài)聯(lián)編聯(lián)編是指一個程序模塊、代碼之間的關(guān)聯(lián)過程,也就是把一個標識符名和一個存儲地址聯(lián)系在一起的過程。按照聯(lián)編進行階段的不同,可以分為靜態(tài)聯(lián)編和動態(tài)聯(lián)編。46.1靜態(tài)聯(lián)編和動態(tài)聯(lián)編聯(lián)編是指一個程序模塊、代碼之6.1靜態(tài)聯(lián)編和動態(tài)聯(lián)編1.靜態(tài)聯(lián)編所謂靜態(tài)聯(lián)編,是指程序之間的匹配、連接工作在編譯階段,即程序運行之前完成,也稱為早期聯(lián)編。函數(shù)重載和運算符重載就屬于靜態(tài)多態(tài)性。所謂函數(shù)重載是指同一個函數(shù)名可以對應(yīng)著多個函數(shù)的實現(xiàn)。每一種函數(shù)的實現(xiàn)對應(yīng)相同的函數(shù)名,但是函數(shù)參數(shù)的個數(shù)不同。56.1靜態(tài)聯(lián)編和動態(tài)聯(lián)編1.靜態(tài)聯(lián)編5【例6.1】參數(shù)個數(shù)不同的重載函數(shù)實例。#include<iostream.h>classMaxClass{private: intx,y,w,h;public: MaxClass(int,int,int,int); intmax(int,int); intmax(int,int,int); intmax(int,int,int,int); voiddisplay();};MaxClass::MaxClass(inta,intb,intc,intd){ x=a;y=b;w=c;h=d;}6【例6.1】參數(shù)個數(shù)不同的重載函數(shù)實例。6intMaxClass::max(inta,intb){ x=a;y=b; returnx>y?x:y;}intMaxClass::max(inta,intb,intc){ w=c; returnmax(a,b)>w?max(a,b):w;}intMaxClass::max(inta,intb,intc,intd){ h=d; returnmax(a,b,c)>d?max(a,b,c):h;}voidMaxClass::display(){ cout<<"四個數(shù)是:"<<x<<","<<y<<","<<w<<","<<h<<endl;}7intMaxClass::max(inta,intb)voidmain(){ MaxClassmc(34,67,143,89); cout<<"計算前兩個數(shù)中的最大數(shù)為:“<<mc.max(34,67)<<endl; cout<<"計算前三個數(shù)中的最大數(shù)為:“<<mc.max(34,67,143)<<endl; cout<<"計算四個數(shù)中的最大數(shù)為:“<<mc.max(34,67,143,89)<<endl; cout<<"其中,"; mc.display();}運行結(jié)果:計算前兩個數(shù)中的最大數(shù)為:67計算前三個數(shù)中的最大數(shù)為:143計算四個數(shù)中的最大數(shù)為:143其中,四個數(shù)是:34,67,143,898voidmain()運行結(jié)果:86.1靜態(tài)聯(lián)編和動態(tài)聯(lián)編2.動態(tài)聯(lián)編與靜態(tài)聯(lián)編相對應(yīng),編譯程序在編譯階段不能確定將要調(diào)用的函數(shù),只有在程序運行階段才能確定調(diào)用的函數(shù)。在編譯、連接過程中無法解決的聯(lián)編問題,要等到程序開始運行之后再來確定該調(diào)用的函數(shù),這種聯(lián)編工作稱為動態(tài)聯(lián)編,也稱為晚期聯(lián)編。C++的動態(tài)聯(lián)編是通過虛函數(shù)和基類的指針實現(xiàn)的,是一種動態(tài)多態(tài)。在后面的例題中可以從中了解。96.1靜態(tài)聯(lián)編和動態(tài)聯(lián)編2.動態(tài)聯(lián)編96.2虛函數(shù)6.2.1虛函數(shù)的定義6.2.2虛函數(shù)與動態(tài)聯(lián)編6.2.3虛函數(shù)的重載6.2.4虛析構(gòu)函數(shù)106.2虛函數(shù)6.2.1虛函數(shù)的定義106.2.1虛函數(shù)的定義引入虛函數(shù)的目的。虛函數(shù)的作用是允許在派生類中重新定義與基類同名的函數(shù),并且可以通過基類指針或引用來訪問基類和派生類中的同名函數(shù)。116.2.1虛函數(shù)的定義引入虛函數(shù)的目的。116.2.1虛函數(shù)的定義2.虛函數(shù)的定義虛函數(shù)的定義是在基類中進行的。虛函數(shù)的定義語法格式如下:virtual<函數(shù)類型><函數(shù)名>(形參表){ 函數(shù)體}126.2.1虛函數(shù)的定義2.虛函數(shù)的定義126.2.1虛函數(shù)的定義3.定義虛函數(shù)時,要注意遵循以下規(guī)則:1)只有成員函數(shù)才能聲明為虛函數(shù),因為虛函數(shù)僅適用于有繼承關(guān)系的類對象,所以普通函數(shù)不能聲明為虛函數(shù)。2)虛函數(shù)的聲明只能出現(xiàn)在類聲明中的函數(shù)原型聲明中,而不能出現(xiàn)在成員的函數(shù)體實現(xiàn)上。3)類的靜態(tài)成員函數(shù)不可以定義為虛函數(shù),因為靜態(tài)成員函數(shù)不受限于某個對象。136.2.1虛函數(shù)的定義3.定義虛函數(shù)時,要注意遵循以6.2.1虛函數(shù)的定義定義虛函數(shù)時,要注意遵循以下規(guī)則:4)類的構(gòu)造函數(shù)不可以定義為虛函數(shù)。多態(tài)是指不同的對象對同一消息有不同的行為特性。虛函數(shù)作為運行過程中多態(tài)的基礎(chǔ),主要是針對對象的,而構(gòu)造函數(shù)是在對象產(chǎn)生之前運行的,因此,虛構(gòu)造函數(shù)是沒有意義的。5)內(nèi)聯(lián)函數(shù)不能聲明為虛函數(shù),因為內(nèi)聯(lián)函數(shù)不能在運行中動態(tài)確定其位置。146.2.1虛函數(shù)的定義定義虛函數(shù)時,要注意遵循以下規(guī)則:6.2.2虛函數(shù)與動態(tài)聯(lián)編虛函數(shù)是動態(tài)聯(lián)編的基礎(chǔ),如果某個類中的一個成員函數(shù)被說明為虛函數(shù),則當(dāng)使用指針或引用所標識的對象操作這個成員函數(shù)時,對該成員函數(shù)調(diào)用采用動態(tài)聯(lián)編的方式,即在運行時進行關(guān)聯(lián)或束定。虛成員函數(shù)是動態(tài)聯(lián)編的,即在運行時是根據(jù)對象類型而不是指向該對象的指針或引用類型選擇成員函數(shù)。動態(tài)聯(lián)編只能通過指針或引用所標識對象來操作虛函數(shù)。156.2.2虛函數(shù)與動態(tài)聯(lián)編虛函數(shù)是動態(tài)聯(lián)編的基礎(chǔ),如果某【例6.5】使用虛函數(shù)例題。#include<iostream.h>#include<string.h>staticintLine=1;classCAnimal //定義基類CAnimal{protected: char*name;public: CAnimal(char*na) { name=newchar[strlen(na)+1]; strcpy(name,na); } virtualvoiddisplay() //虛函數(shù)聲明 { cout<<"("<<Line++<<"):動物(食草/食肉)."<<endl; }};16【例6.5】使用虛函數(shù)例題。16classCHerbivorous:publicCAnimal//定義派生類CHerbivorous{public: CHerbivorous(char*na):CAnimal(na){} voiddisplay() //重新定義虛函數(shù) { cout<<"("<<Line++<<"):食草動物:"<<name<<endl; }};//定義派生類CCarnivore(食肉動物)classCCarnivore:publicCAnimal {public: CCarnivore(char*na):CAnimal(na){} voiddisplay() //重新定義虛函數(shù) { cout<<"("<<Line++<<"):食肉動物:"<<name<<endl; }};17classCHerbivorous:publicCAnivoidmain(){ CAnimalanimal(""),*ptrAni; CHerbivorousherb("羚羊"); CCarnivorecarn("老虎"); ptrAni=&animal; ptrAni->display(); ptrAni=&herb; ptrAni->display(); ((CHerbivorous*)ptrAni)->display(); ptrAni=&carn; ptrAni->display(); ((CCarnivore*)ptrAni)->display(); herb.display(); carn.display();}運行結(jié)果:(1):動物(食草/食肉).(2):食草動物:羚羊(3):食草動物:羚羊(4):食肉動物:老虎(5):食肉動物:老虎(6):食草動物:羚羊(7):食肉動物:老虎18voidmain()運行結(jié)果:186.2.3虛函數(shù)的重載1.虛函數(shù)與重載的關(guān)系一般的函數(shù)重載,只要函數(shù)名相同,函數(shù)的所帶參數(shù)的個數(shù)、類型或次序不同。當(dāng)重載一個虛函數(shù)時,也就是說在派生類中重新定義此虛函數(shù)時,要求函數(shù)名、返回類型、參數(shù)個數(shù)、參數(shù)類型以及參數(shù)的順序都與基類中的原型完全相同,不能有任何的不同?!纠?.7】虛函數(shù)重載。196.2.3虛函數(shù)的重載1.虛函數(shù)與重載的關(guān)系19#include<iostream.h>#include<string.h>classperson{protected: char*name;public: person(char*n) { name=newchar[strlen(n)+1]; strcpy(name,n); } ~person() {delete[]name;}virtualvoidprintInfo() //基類中的函數(shù){ cout<<"姓名:"<<name<<"\n"; }};20#include<iostream.h>20classworker:publicperson{private:char*type;public: worker(char*na,char*t="SteelWorker"):person(na) { type=newchar[strlen(t)+1]; strcpy(type,t); } ~worker(){ delete[]type;}voidprintInfo() //在派生類worker中重新定義{ cout<<name<<","; cout<<type<<endl; }};21classworker:publicperson21classteacher:publicperson{private:char*subject;public: teacher(char*na,char*s):person(na) { subject=newchar[strlen(s)+1]; strcpy(subject,s); } ~teacher(){delete[]subject; }voidprintInfo() //在派生類teacher中重新定義{ cout<<name<<","; cout<<subject<<"教師"<<endl; }};22classteacher:publicperson22voidmain(){workerw("張曉強","園林工人");teachert("李文卓","生命科學(xué)");person*p;p=&w;p->printInfo();p=&t;p->printInfo();}運行結(jié)果:張曉強,園林工人李文卓,生命科學(xué)教師23voidmain()運行結(jié)果:236.2.3虛函數(shù)的重載2.多繼承中的虛函數(shù)【例6.8】多繼承中使用虛函數(shù)例題。#include<iostream.h>classbase1 //定義基類base1{public: virtualvoiddisplay() //函數(shù)定義為虛函數(shù) { cout<<"基類base1."<<endl; }};246.2.3虛函數(shù)的重載2.多繼承中的虛函數(shù)24classbase2 //定義基類base2{public: voiddisplay() //函數(shù)為一般成員函數(shù) { cout<<"基類base2."<<endl; }};classderive:publicbase1,publicbase2{public: voiddisplay() { cout<<"派生類derive公有繼承base1和base2."<<endl; }};25classbase2 //定義基類base225voidmain(){ base1obj1,*ptr1; base2obj2,*ptr2; deriveobj3; ptr1=&obj1; ptr1->display(); ptr1=&obj3; ptr1->display();//動態(tài)聯(lián)編,ptr1類型為derive類型 ptr2=&obj2; ptr2->display(); ptr2=&obj3; ptr2->display();//靜態(tài)聯(lián)編,ptr1類型為base2類型}運行結(jié)果:基類base1.派生類derive公有繼承base1和base2.基類base2.基類base2.26voidmain()運行結(jié)果:266.2.4虛析構(gòu)函數(shù)在析構(gòu)函數(shù)前面冠以關(guān)鍵字virtual進行說明,則稱該析構(gòu)函數(shù)為虛析構(gòu)函數(shù)。虛析構(gòu)函數(shù)的聲明語法格式如下:virtual~類名()例如:classexample{public:virtual~example();…};276.2.4虛析構(gòu)函數(shù)在析構(gòu)函數(shù)前面冠以關(guān)鍵字virtua6.3純虛函數(shù)和抽象類6.3.1純虛函數(shù)6.3.2抽象類286.3純虛函數(shù)和抽象類6.3.1純虛函數(shù)286.3.1純虛函數(shù)一些類表示沒有具體意義的抽象概念,它不能為其虛函數(shù)提供具體的定義,因此可以定義為純虛函數(shù)。純虛函數(shù)是一個在基類中說明的虛函數(shù),它在該基類中只有一個函數(shù)聲明,并沒有具體函數(shù)功能的實現(xiàn)。純虛函數(shù)的聲明形式如下:
virtual<函數(shù)類型><函數(shù)名>(參數(shù)表)=0;不能創(chuàng)建含有一個或多個純虛函數(shù)的類對象,純虛函數(shù)不可以直接調(diào)用,也不可以被繼承。296.3.1純虛函數(shù)一些類表示沒有具體意義的抽象概念,它6.3.2抽象類包含一個或多個純虛函數(shù)的類稱為抽象類。由于抽象類中的純虛函數(shù)沒有具體的函數(shù)實現(xiàn),因此不能定義抽象類的對象。抽象類只能作為基類被子類繼承,其純虛函數(shù)的實現(xiàn)由派生類給出。抽象類的重要用處是提供一個接口,而不揭示任何實現(xiàn)的細節(jié)。抽象類不能用作參數(shù)類型、函數(shù)返回類型或強制類型轉(zhuǎn)換。但是,可以聲明抽象類的指針和引用。306.3.2抽象類包含一個或多個純虛函數(shù)的類稱為抽象類。30【例6.14】使用抽象指針。#include<iostream.h>classCPoint //抽象基類CPoint聲明{protected: longx,y;public: CPoint(intxx=0,intyy=0) { x=xx; y=yy; } virtualvoiddisplay()=0; //純虛函數(shù)成員};31【例6.14】使用抽象指針。31classCRectangle:publicCPoint //派生類Rectangle聲明{private: doublewidth,height;public: CRectangle(longx,longy,doublew,doubleh):CPoint(x,y) { width=w; height=h; } voiddisplay() //虛成員函數(shù) { cout<<"矩形"<<endl; cout<<"位置:("<<x<<","<<y<<")"<<endl; cout<<"長="<<width<<",寬="<<height<<endl; }};32classCRectangle:publicCPointclassCTriangle:publicCPoint //派生類CTriangle聲明{private: doublea,b,c;public: CTriangle(longx,longy,doublea1,doubleb1,doublec1):CPoint(x,y){ a=a1; b=b1;c=c1; } voiddisplay() //虛成員函數(shù) { cout<<"三角形"<<endl; cout<<"位置:("<<x<<","<<y<<")"<<endl; cout<<"三邊長:"<<a<<","<<b<<","<<c<<endl;
}};33classCTriangle:publicCPoint voidmain(){ CPoint*ptr[2]; //聲明抽象基類指針 CRectangler1(10,10,120,60); CTrianglet1(50,50,345,456,567); ptr[0]=&r1; //指針指向CRectangle類對象 ptr[0]->display(); cout<<"-----------------------\n"; ptr[1]=&t1; //指針指向CTriangle類對象 ptr[1]->display();}運行結(jié)果:矩形位置:(10,10)長=120,寬=60-----------------------三角形位置:(50,50)三邊長:345,456,56734voidmain()運行結(jié)果:346.4多態(tài)356.4多態(tài)356.4多態(tài)6.4.1多態(tài)的含義6.4.2多態(tài)的應(yīng)用366.4多態(tài)6.4.1多態(tài)的含義366.4.1多態(tài)的含義所謂多態(tài)性是指同一個接口被不同的對象操作產(chǎn)生不同的響應(yīng)。面向?qū)ο蟮亩鄳B(tài)性從實現(xiàn)的角度來講,可以分為靜態(tài)多態(tài)性和動態(tài)多態(tài)性兩種。靜態(tài)多態(tài)性是在編譯的過程中確定同名操作的具體操作對象的,而動態(tài)多態(tài)性則是在程序運行過程中動態(tài)地確定操作所針對的具體對象的。所謂消息,是指對類的成員函數(shù)的調(diào)用。不同的方法是指不同的實現(xiàn),也就是調(diào)用了不同的函數(shù)。376.4.1多態(tài)的含義所謂多態(tài)性是指同一個接口被不同的對象6.4.1多態(tài)的含義動態(tài)多態(tài)是通過虛函數(shù)來實現(xiàn)的,虛函數(shù)的使用本質(zhì)是將派生類類型的指針賦給基類類型的指針,虛函數(shù)被調(diào)用時會自動判斷調(diào)用對象的類型,從而做出相應(yīng)的響應(yīng)?!纠?.16】多態(tài)應(yīng)用舉例。#include<iostream.h>constdoublePi=3.141593;classShapes{public:virtualvoiddraw()=0; //基類中的純虛函數(shù)virtualdoublearea()=0; //基類中的純虛函數(shù)};386.4.1多態(tài)的含義動態(tài)多態(tài)是通過虛函數(shù)來實現(xiàn)的,虛函數(shù)classCircle:publicShapes{private:doubleradius;public:Circle(doubler) { radius=r;} voiddraw() //在派生類中實現(xiàn){ cout<<"Drawcircle."<<endl; cout<<"Radius="<<radius<<endl; } doublearea() //在派生類中實現(xiàn) { returnPi*radius*radius; }};39classCircle:publicShapes39classSquare:publicShapes{private:doublelength;public: Square(doublelen) { length=len; }voiddraw() //在派生類中實現(xiàn) { cout<<"Drawsquare."<<endl; cout<<"Length="<<length<<endl; } doublearea() { returnlength*length; }};40classSquare:publicShapes40voidmain(){Circlec(10);Squares(12);Shapes*ptr;ptr=&c;ptr->draw();cout<<"Circlearea:"<<ptr->area()<<endl;cout<<"--------------------------\n";ptr=&s;ptr->draw();cout<<"Squarearea:"<<ptr->area()<<endl;}運行結(jié)果:Drawcircle.Radius=10Circlearea:314.159--------------------------Drawsquare.Length=12Squarearea:14441voidmain()運行結(jié)果:416.4.2多態(tài)的應(yīng)用【例6.18】設(shè)計動物類Animal,提供純虛函數(shù)food()顯示不同動物的食物;派生類Elephant類表示大象類,具體實現(xiàn)成員函數(shù)food()顯示Elephant的食物,派生類Lion類表示獅子類,具體實現(xiàn)成員函數(shù)food()顯示Lion的食物。定義普通函數(shù)ShowFood(),其參數(shù)類型為Animal類的指針,通過指針調(diào)用food()成員函數(shù)。426.4.2多態(tài)的應(yīng)用【例6.18】設(shè)計動物類Animal#include<iostream.h>classAnimal //定義Animal類{public: virtualvoidfood()=0;//成員函數(shù)food()為純虛函數(shù)。};classElephant:publicAnimal //定義派生類Elephant類繼承類Animal{public: voidfood(); //包含成員函數(shù)food()};classLion:publicAnimal //定義派生類Lion類繼承類Animal{public: voidfood(); //包含成員函數(shù)food()};43#include<iostream.h>43voidElephant::food(){cout<<"Elephantfeedongrass."<<endl;}voidLion::food(){cout<<"Lionfeedonmeat."<<endl;}voidShowFood(Animal*ptr){ptr->food();}voidmain(){ Elephantelep1; Lionlion1; Animal*Aniptr; elep1.food(); lion1.food(); cout<<"------------------------"<<endl; Aniptr=&elep1; ShowFood(Aniptr); Aniptr=&lion1; ShowFood(Aniptr);}運行結(jié)果:Elephantfeedongrass.Lionfeedonmeat.------------------------Elephantfeedongrass.Lionfeedonmeat.44voidElephant::food()運行結(jié)果:44總結(jié)介紹了靜態(tài)聯(lián)編和動態(tài)聯(lián)編的含義;講解了虛函數(shù)的作用和定義;講解了虛析構(gòu)函數(shù)的作用和定義;講解了純虛函數(shù)和抽象類的概念和應(yīng)用;介紹了多態(tài)性的應(yīng)用。45總結(jié)介紹了靜態(tài)聯(lián)編和動態(tài)聯(lián)編的含義;45第六章虛函數(shù)和多態(tài)性46第六章虛函數(shù)和多態(tài)性1目標理解靜態(tài)聯(lián)編和動態(tài)聯(lián)編的含義熟練掌握虛函數(shù)的使用掌握虛析構(gòu)函數(shù)的作用掌握抽象類掌握多態(tài)性47目標理解靜態(tài)聯(lián)編和動態(tài)聯(lián)編的含義26.1靜態(tài)聯(lián)編和動態(tài)聯(lián)編486.1靜態(tài)聯(lián)編和動態(tài)聯(lián)編36.1靜態(tài)聯(lián)編和動態(tài)聯(lián)編聯(lián)編是指一個程序模塊、代碼之間的關(guān)聯(lián)過程,也就是把一個標識符名和一個存儲地址聯(lián)系在一起的過程。按照聯(lián)編進行階段的不同,可以分為靜態(tài)聯(lián)編和動態(tài)聯(lián)編。496.1靜態(tài)聯(lián)編和動態(tài)聯(lián)編聯(lián)編是指一個程序模塊、代碼之6.1靜態(tài)聯(lián)編和動態(tài)聯(lián)編1.靜態(tài)聯(lián)編所謂靜態(tài)聯(lián)編,是指程序之間的匹配、連接工作在編譯階段,即程序運行之前完成,也稱為早期聯(lián)編。函數(shù)重載和運算符重載就屬于靜態(tài)多態(tài)性。所謂函數(shù)重載是指同一個函數(shù)名可以對應(yīng)著多個函數(shù)的實現(xiàn)。每一種函數(shù)的實現(xiàn)對應(yīng)相同的函數(shù)名,但是函數(shù)參數(shù)的個數(shù)不同。506.1靜態(tài)聯(lián)編和動態(tài)聯(lián)編1.靜態(tài)聯(lián)編5【例6.1】參數(shù)個數(shù)不同的重載函數(shù)實例。#include<iostream.h>classMaxClass{private: intx,y,w,h;public: MaxClass(int,int,int,int); intmax(int,int); intmax(int,int,int); intmax(int,int,int,int); voiddisplay();};MaxClass::MaxClass(inta,intb,intc,intd){ x=a;y=b;w=c;h=d;}51【例6.1】參數(shù)個數(shù)不同的重載函數(shù)實例。6intMaxClass::max(inta,intb){ x=a;y=b; returnx>y?x:y;}intMaxClass::max(inta,intb,intc){ w=c; returnmax(a,b)>w?max(a,b):w;}intMaxClass::max(inta,intb,intc,intd){ h=d; returnmax(a,b,c)>d?max(a,b,c):h;}voidMaxClass::display(){ cout<<"四個數(shù)是:"<<x<<","<<y<<","<<w<<","<<h<<endl;}52intMaxClass::max(inta,intb)voidmain(){ MaxClassmc(34,67,143,89); cout<<"計算前兩個數(shù)中的最大數(shù)為:“<<mc.max(34,67)<<endl; cout<<"計算前三個數(shù)中的最大數(shù)為:“<<mc.max(34,67,143)<<endl; cout<<"計算四個數(shù)中的最大數(shù)為:“<<mc.max(34,67,143,89)<<endl; cout<<"其中,"; mc.display();}運行結(jié)果:計算前兩個數(shù)中的最大數(shù)為:67計算前三個數(shù)中的最大數(shù)為:143計算四個數(shù)中的最大數(shù)為:143其中,四個數(shù)是:34,67,143,8953voidmain()運行結(jié)果:86.1靜態(tài)聯(lián)編和動態(tài)聯(lián)編2.動態(tài)聯(lián)編與靜態(tài)聯(lián)編相對應(yīng),編譯程序在編譯階段不能確定將要調(diào)用的函數(shù),只有在程序運行階段才能確定調(diào)用的函數(shù)。在編譯、連接過程中無法解決的聯(lián)編問題,要等到程序開始運行之后再來確定該調(diào)用的函數(shù),這種聯(lián)編工作稱為動態(tài)聯(lián)編,也稱為晚期聯(lián)編。C++的動態(tài)聯(lián)編是通過虛函數(shù)和基類的指針實現(xiàn)的,是一種動態(tài)多態(tài)。在后面的例題中可以從中了解。546.1靜態(tài)聯(lián)編和動態(tài)聯(lián)編2.動態(tài)聯(lián)編96.2虛函數(shù)6.2.1虛函數(shù)的定義6.2.2虛函數(shù)與動態(tài)聯(lián)編6.2.3虛函數(shù)的重載6.2.4虛析構(gòu)函數(shù)556.2虛函數(shù)6.2.1虛函數(shù)的定義106.2.1虛函數(shù)的定義引入虛函數(shù)的目的。虛函數(shù)的作用是允許在派生類中重新定義與基類同名的函數(shù),并且可以通過基類指針或引用來訪問基類和派生類中的同名函數(shù)。566.2.1虛函數(shù)的定義引入虛函數(shù)的目的。116.2.1虛函數(shù)的定義2.虛函數(shù)的定義虛函數(shù)的定義是在基類中進行的。虛函數(shù)的定義語法格式如下:virtual<函數(shù)類型><函數(shù)名>(形參表){ 函數(shù)體}576.2.1虛函數(shù)的定義2.虛函數(shù)的定義126.2.1虛函數(shù)的定義3.定義虛函數(shù)時,要注意遵循以下規(guī)則:1)只有成員函數(shù)才能聲明為虛函數(shù),因為虛函數(shù)僅適用于有繼承關(guān)系的類對象,所以普通函數(shù)不能聲明為虛函數(shù)。2)虛函數(shù)的聲明只能出現(xiàn)在類聲明中的函數(shù)原型聲明中,而不能出現(xiàn)在成員的函數(shù)體實現(xiàn)上。3)類的靜態(tài)成員函數(shù)不可以定義為虛函數(shù),因為靜態(tài)成員函數(shù)不受限于某個對象。586.2.1虛函數(shù)的定義3.定義虛函數(shù)時,要注意遵循以6.2.1虛函數(shù)的定義定義虛函數(shù)時,要注意遵循以下規(guī)則:4)類的構(gòu)造函數(shù)不可以定義為虛函數(shù)。多態(tài)是指不同的對象對同一消息有不同的行為特性。虛函數(shù)作為運行過程中多態(tài)的基礎(chǔ),主要是針對對象的,而構(gòu)造函數(shù)是在對象產(chǎn)生之前運行的,因此,虛構(gòu)造函數(shù)是沒有意義的。5)內(nèi)聯(lián)函數(shù)不能聲明為虛函數(shù),因為內(nèi)聯(lián)函數(shù)不能在運行中動態(tài)確定其位置。596.2.1虛函數(shù)的定義定義虛函數(shù)時,要注意遵循以下規(guī)則:6.2.2虛函數(shù)與動態(tài)聯(lián)編虛函數(shù)是動態(tài)聯(lián)編的基礎(chǔ),如果某個類中的一個成員函數(shù)被說明為虛函數(shù),則當(dāng)使用指針或引用所標識的對象操作這個成員函數(shù)時,對該成員函數(shù)調(diào)用采用動態(tài)聯(lián)編的方式,即在運行時進行關(guān)聯(lián)或束定。虛成員函數(shù)是動態(tài)聯(lián)編的,即在運行時是根據(jù)對象類型而不是指向該對象的指針或引用類型選擇成員函數(shù)。動態(tài)聯(lián)編只能通過指針或引用所標識對象來操作虛函數(shù)。606.2.2虛函數(shù)與動態(tài)聯(lián)編虛函數(shù)是動態(tài)聯(lián)編的基礎(chǔ),如果某【例6.5】使用虛函數(shù)例題。#include<iostream.h>#include<string.h>staticintLine=1;classCAnimal //定義基類CAnimal{protected: char*name;public: CAnimal(char*na) { name=newchar[strlen(na)+1]; strcpy(name,na); } virtualvoiddisplay() //虛函數(shù)聲明 { cout<<"("<<Line++<<"):動物(食草/食肉)."<<endl; }};61【例6.5】使用虛函數(shù)例題。16classCHerbivorous:publicCAnimal//定義派生類CHerbivorous{public: CHerbivorous(char*na):CAnimal(na){} voiddisplay() //重新定義虛函數(shù) { cout<<"("<<Line++<<"):食草動物:"<<name<<endl; }};//定義派生類CCarnivore(食肉動物)classCCarnivore:publicCAnimal {public: CCarnivore(char*na):CAnimal(na){} voiddisplay() //重新定義虛函數(shù) { cout<<"("<<Line++<<"):食肉動物:"<<name<<endl; }};62classCHerbivorous:publicCAnivoidmain(){ CAnimalanimal(""),*ptrAni; CHerbivorousherb("羚羊"); CCarnivorecarn("老虎"); ptrAni=&animal; ptrAni->display(); ptrAni=&herb; ptrAni->display(); ((CHerbivorous*)ptrAni)->display(); ptrAni=&carn; ptrAni->display(); ((CCarnivore*)ptrAni)->display(); herb.display(); carn.display();}運行結(jié)果:(1):動物(食草/食肉).(2):食草動物:羚羊(3):食草動物:羚羊(4):食肉動物:老虎(5):食肉動物:老虎(6):食草動物:羚羊(7):食肉動物:老虎63voidmain()運行結(jié)果:186.2.3虛函數(shù)的重載1.虛函數(shù)與重載的關(guān)系一般的函數(shù)重載,只要函數(shù)名相同,函數(shù)的所帶參數(shù)的個數(shù)、類型或次序不同。當(dāng)重載一個虛函數(shù)時,也就是說在派生類中重新定義此虛函數(shù)時,要求函數(shù)名、返回類型、參數(shù)個數(shù)、參數(shù)類型以及參數(shù)的順序都與基類中的原型完全相同,不能有任何的不同?!纠?.7】虛函數(shù)重載。646.2.3虛函數(shù)的重載1.虛函數(shù)與重載的關(guān)系19#include<iostream.h>#include<string.h>classperson{protected: char*name;public: person(char*n) { name=newchar[strlen(n)+1]; strcpy(name,n); } ~person() {delete[]name;}virtualvoidprintInfo() //基類中的函數(shù){ cout<<"姓名:"<<name<<"\n"; }};65#include<iostream.h>20classworker:publicperson{private:char*type;public: worker(char*na,char*t="SteelWorker"):person(na) { type=newchar[strlen(t)+1]; strcpy(type,t); } ~worker(){ delete[]type;}voidprintInfo() //在派生類worker中重新定義{ cout<<name<<","; cout<<type<<endl; }};66classworker:publicperson21classteacher:publicperson{private:char*subject;public: teacher(char*na,char*s):person(na) { subject=newchar[strlen(s)+1]; strcpy(subject,s); } ~teacher(){delete[]subject; }voidprintInfo() //在派生類teacher中重新定義{ cout<<name<<","; cout<<subject<<"教師"<<endl; }};67classteacher:publicperson22voidmain(){workerw("張曉強","園林工人");teachert("李文卓","生命科學(xué)");person*p;p=&w;p->printInfo();p=&t;p->printInfo();}運行結(jié)果:張曉強,園林工人李文卓,生命科學(xué)教師68voidmain()運行結(jié)果:236.2.3虛函數(shù)的重載2.多繼承中的虛函數(shù)【例6.8】多繼承中使用虛函數(shù)例題。#include<iostream.h>classbase1 //定義基類base1{public: virtualvoiddisplay() //函數(shù)定義為虛函數(shù) { cout<<"基類base1."<<endl; }};696.2.3虛函數(shù)的重載2.多繼承中的虛函數(shù)24classbase2 //定義基類base2{public: voiddisplay() //函數(shù)為一般成員函數(shù) { cout<<"基類base2."<<endl; }};classderive:publicbase1,publicbase2{public: voiddisplay() { cout<<"派生類derive公有繼承base1和base2."<<endl; }};70classbase2 //定義基類base225voidmain(){ base1obj1,*ptr1; base2obj2,*ptr2; deriveobj3; ptr1=&obj1; ptr1->display(); ptr1=&obj3; ptr1->display();//動態(tài)聯(lián)編,ptr1類型為derive類型 ptr2=&obj2; ptr2->display(); ptr2=&obj3; ptr2->display();//靜態(tài)聯(lián)編,ptr1類型為base2類型}運行結(jié)果:基類base1.派生類derive公有繼承base1和base2.基類base2.基類base2.71voidmain()運行結(jié)果:266.2.4虛析構(gòu)函數(shù)在析構(gòu)函數(shù)前面冠以關(guān)鍵字virtual進行說明,則稱該析構(gòu)函數(shù)為虛析構(gòu)函數(shù)。虛析構(gòu)函數(shù)的聲明語法格式如下:virtual~類名()例如:classexample{public:virtual~example();…};726.2.4虛析構(gòu)函數(shù)在析構(gòu)函數(shù)前面冠以關(guān)鍵字virtua6.3純虛函數(shù)和抽象類6.3.1純虛函數(shù)6.3.2抽象類736.3純虛函數(shù)和抽象類6.3.1純虛函數(shù)286.3.1純虛函數(shù)一些類表示沒有具體意義的抽象概念,它不能為其虛函數(shù)提供具體的定義,因此可以定義為純虛函數(shù)。純虛函數(shù)是一個在基類中說明的虛函數(shù),它在該基類中只有一個函數(shù)聲明,并沒有具體函數(shù)功能的實現(xiàn)。純虛函數(shù)的聲明形式如下:
virtual<函數(shù)類型><函數(shù)名>(參數(shù)表)=0;不能創(chuàng)建含有一個或多個純虛函數(shù)的類對象,純虛函數(shù)不可以直接調(diào)用,也不可以被繼承。746.3.1純虛函數(shù)一些類表示沒有具體意義的抽象概念,它6.3.2抽象類包含一個或多個純虛函數(shù)的類稱為抽象類。由于抽象類中的純虛函數(shù)沒有具體的函數(shù)實現(xiàn),因此不能定義抽象類的對象。抽象類只能作為基類被子類繼承,其純虛函數(shù)的實現(xiàn)由派生類給出。抽象類的重要用處是提供一個接口,而不揭示任何實現(xiàn)的細節(jié)。抽象類不能用作參數(shù)類型、函數(shù)返回類型或強制類型轉(zhuǎn)換。但是,可以聲明抽象類的指針和引用。756.3.2抽象類包含一個或多個純虛函數(shù)的類稱為抽象類。30【例6.14】使用抽象指針。#include<iostream.h>classCPoint //抽象基類CPoint聲明{protected: longx,y;public: CPoint(intxx=0,intyy=0) { x=xx; y=yy; } virtualvoiddisplay()=0; //純虛函數(shù)成員};76【例6.14】使用抽象指針。31classCRectangle:publicCPoint //派生類Rectangle聲明{private: doublewidth,height;public: CRectangle(longx,longy,doublew,doubleh):CPoint(x,y) { width=w; height=h; } voiddisplay() //虛成員函數(shù) { cout<<"矩形"<<endl; cout<<"位置:("<<x<<","<<y<<")"<<endl; cout<<"長="<<width<<",寬="<<height<<endl; }};77classCRectangle:publicCPointclassCTriangle:publicCPoint //派生類CTriangle聲明{private: doublea,b,c;public: CTriangle(longx,longy,doublea1,doubleb1,doublec1):CPoint(x,y){ a=a1; b=b1;c=c1; } voiddisplay() //虛成員函數(shù) { cout<<"三角形"<<endl; cout<<"位置:("<<x<<","<<y<<")"<<endl; cout<<"三邊長:"<<a<<","<<b<<","<<c<<endl;
}};78classCTriangle:publicCPoint voidmain(){ CPoint*ptr[2]; //聲明抽象基類指針 CRectangler1(10,10,120,60); CTrianglet1(50,50,345,456,567); ptr[0]=&r1; //指針指向CRectangle類對象 ptr[0]->display(); cout<<"-----------------------\n"; ptr[1]=&t1; //指針指向CTriangle類對象 ptr[1]->display();}運行結(jié)果:矩形位置:(10,10)長=120,寬=60-----------------------三角形位置:(50,50)三邊長:345,456,56779voidmain()運行結(jié)果:346.4多態(tài)806.4多態(tài)356.4多態(tài)6.4.1多態(tài)的含義6.4.2多態(tài)的應(yīng)用816.4多態(tài)6.4.1多態(tài)的含義366.4.1多態(tài)的含義所謂多態(tài)性是指同一個接口被不同的對象操作產(chǎn)生不同的響應(yīng)。面向?qū)ο蟮亩鄳B(tài)性從實現(xiàn)的角度來講,可以分為靜態(tài)多態(tài)性和動態(tài)多態(tài)性兩種。靜態(tài)多態(tài)性是在編譯的過程中確定同名操作的具體操作對象的,而動態(tài)多態(tài)性則是在程序運行過程中動態(tài)地確定操作所針對的具體對象的。所謂消息,是指對類的成員函數(shù)的調(diào)用。不同的方法是指不同的實現(xiàn),也就是調(diào)用了不同的函數(shù)。826.4.1多態(tài)的含義所謂多態(tài)性是指同一個接口被不同的對象6.4.1多態(tài)的含義動態(tài)多態(tài)是通過虛函數(shù)來實現(xiàn)的,虛函數(shù)的使用本質(zhì)是將派生類類型的指針賦給基類類型的指針,虛函數(shù)被調(diào)用時會自動判斷調(diào)用對象的類型,從而做出相應(yīng)的響應(yīng)?!纠?.16】多態(tài)應(yīng)用舉例。#include<iostream.h>constdoublePi=3.141593;classShapes{public:virtualvoiddraw()=0; //基類中的純虛函數(shù)virtualdoublearea()=0; //基類中的純虛函數(shù)};836.4.1多態(tài)的含義動態(tài)多態(tài)是通過虛函數(shù)來實現(xiàn)的,虛函數(shù)classCircle:publicShapes{private:doubleradius;public:
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024-2030年全球及中國純素護膚品行業(yè)營銷策略及盈利前景預(yù)測報告
- 2024-2030年全球及中國汽車空氣懸架再制造行業(yè)銷售規(guī)模與需求狀況預(yù)測報告版
- 2024-2030年全球及中國旅行者腹瀉(TD)用藥行業(yè)運行狀況及需求規(guī)模預(yù)測報告
- 2024-2030年全球及中國小型發(fā)動機排放控制催化劑行業(yè)需求趨勢及投資前景預(yù)測報告
- 2024年農(nóng)民專業(yè)合作社股權(quán)買賣合同
- 2024-2030年中國鮮肉腸行業(yè)市場銷售模式及投資盈利預(yù)測報告
- 2024-2030年中國高端家具行業(yè)競爭力策略及發(fā)展規(guī)劃分析報告版
- 2024-2030年中國骨科器械行業(yè)前景展望及投資戰(zhàn)略規(guī)劃分析報告
- 2024-2030年中國長短風(fēng)衣行業(yè)供需狀況發(fā)展戰(zhàn)略規(guī)劃分析報告
- GA 1809-2022城市供水系統(tǒng)反恐怖防范要求
- 幼兒園繪本故事:《老虎拔牙》 課件
- 2021年上半年《系統(tǒng)集成項目管理工程師》真題
- 一個冬天的童話 遇羅錦
- GB/T 706-2008熱軋型鋼
- 實驗六 雙子葉植物莖的初生結(jié)構(gòu)和單子葉植物莖的結(jié)構(gòu)
- GB/T 25032-2010生活垃圾焚燒爐渣集料
- GB/T 13610-2020天然氣的組成分析氣相色譜法
- 《彩虹》教案 省賽一等獎
- 2023年湖南建筑工程初中級職稱考試基礎(chǔ)知識
- 沈陽機場航站樓擴建工程安裝施工組織設(shè)計
評論
0/150
提交評論