版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、 多態(tài)性是面向?qū)ο蟪绦蛟O(shè)計(jì)語言的又一重要特征,它是指不同多態(tài)性是面向?qū)ο蟪绦蛟O(shè)計(jì)語言的又一重要特征,它是指不同對(duì)象接收到同一消息時(shí)會(huì)產(chǎn)生不同的行為。對(duì)象接收到同一消息時(shí)會(huì)產(chǎn)生不同的行為。 繼承所處理的是類與類之間的層次關(guān)系問題,而多態(tài)則是處理繼承所處理的是類與類之間的層次關(guān)系問題,而多態(tài)則是處理類的層次結(jié)構(gòu)之間,以及同一個(gè)類內(nèi)部同名函數(shù)的關(guān)系問題。類的層次結(jié)構(gòu)之間,以及同一個(gè)類內(nèi)部同名函數(shù)的關(guān)系問題。 簡單地說,多態(tài)就是在同一個(gè)類或繼承體系結(jié)構(gòu)的基類與派生簡單地說,多態(tài)就是在同一個(gè)類或繼承體系結(jié)構(gòu)的基類與派生類中,用同名函數(shù)來實(shí)現(xiàn)各種不同的功能。類中,用同名函數(shù)來實(shí)現(xiàn)各種不同的功能。 多態(tài)是面
2、向?qū)ο罄碚摰娜笾е?。另外兩個(gè)支柱是封裝和多態(tài)是面向?qū)ο罄碚摰娜笾е?。另外兩個(gè)支柱是封裝和繼承。繼承。1. 多態(tài)多態(tài)(polymorphism) 對(duì)象根據(jù)所接收的消息而做出動(dòng)作,同樣的消息為不同的對(duì)象對(duì)象根據(jù)所接收的消息而做出動(dòng)作,同樣的消息為不同的對(duì)象接收時(shí)可導(dǎo)致完全不同的行動(dòng),該現(xiàn)象稱為多態(tài)性。接收時(shí)可導(dǎo)致完全不同的行動(dòng),該現(xiàn)象稱為多態(tài)性。6.1 多態(tài)的概念多態(tài)的概念 通俗地講,就是用一個(gè)相同的名字定義許多不同的函數(shù),這些通俗地講,就是用一個(gè)相同的名字定義許多不同的函數(shù),這些函數(shù)可以針對(duì)不同數(shù)據(jù)類型實(shí)現(xiàn)相同或相似的功能,即一個(gè)接口,函數(shù)可以針對(duì)不同數(shù)據(jù)類型實(shí)現(xiàn)相同或相似的功能,即
3、一個(gè)接口,多種實(shí)現(xiàn)。多種實(shí)現(xiàn)。2. 聯(lián)編聯(lián)編 C+中的多態(tài)性與聯(lián)編這一概念密切相關(guān)。一個(gè)程序常常會(huì)調(diào)中的多態(tài)性與聯(lián)編這一概念密切相關(guān)。一個(gè)程序常常會(huì)調(diào)用到來自于不同文件或用到來自于不同文件或C+庫中的資源庫中的資源(如函數(shù)、對(duì)話框如函數(shù)、對(duì)話框)等,需等,需要經(jīng)過編譯、連接才能形成可執(zhí)行文件,在這個(gè)過程中要把調(diào)用要經(jīng)過編譯、連接才能形成可執(zhí)行文件,在這個(gè)過程中要把調(diào)用函數(shù)名與對(duì)應(yīng)函數(shù)函數(shù)名與對(duì)應(yīng)函數(shù)(這些函數(shù)可能來源于不同的文件或庫這些函數(shù)可能來源于不同的文件或庫)關(guān)聯(lián)在關(guān)聯(lián)在一起,這個(gè)過程稱為綁定一起,這個(gè)過程稱為綁定(binding),即聯(lián)編。,即聯(lián)編。3. 靜態(tài)聯(lián)編與動(dòng)態(tài)聯(lián)編靜態(tài)聯(lián)編與動(dòng)
4、態(tài)聯(lián)編(1)靜態(tài)聯(lián)編靜態(tài)聯(lián)編 在編譯程序時(shí)根據(jù)調(diào)用函數(shù)提供的信息,把它所對(duì)應(yīng)的具體函在編譯程序時(shí)根據(jù)調(diào)用函數(shù)提供的信息,把它所對(duì)應(yīng)的具體函數(shù)確定下來,即在編譯時(shí)把調(diào)用函數(shù)名與具體函數(shù)綁定在一起。數(shù)確定下來,即在編譯時(shí)把調(diào)用函數(shù)名與具體函數(shù)綁定在一起。(2)動(dòng)態(tài)聯(lián)編動(dòng)態(tài)聯(lián)編 在編譯程序時(shí)還不能確定函數(shù)調(diào)用所對(duì)應(yīng)的具體函數(shù),只有在在編譯程序時(shí)還不能確定函數(shù)調(diào)用所對(duì)應(yīng)的具體函數(shù),只有在程序運(yùn)行過程中才能確定函數(shù)調(diào)用所對(duì)應(yīng)的具體函數(shù),即在程序程序運(yùn)行過程中才能確定函數(shù)調(diào)用所對(duì)應(yīng)的具體函數(shù),即在程序運(yùn)行時(shí)才把調(diào)用函數(shù)名與具體函數(shù)綁定在一起。運(yùn)行時(shí)才把調(diào)用函數(shù)名與具體函數(shù)綁定在一起。4. 多態(tài)性的實(shí)現(xiàn)多態(tài)
5、性的實(shí)現(xiàn)(1)編譯時(shí)多態(tài)性編譯時(shí)多態(tài)性-靜態(tài)聯(lián)編靜態(tài)聯(lián)編(連接連接) 系統(tǒng)在編譯時(shí)就決定如何實(shí)現(xiàn)某一動(dòng)作,即對(duì)某一消息如何處系統(tǒng)在編譯時(shí)就決定如何實(shí)現(xiàn)某一動(dòng)作,即對(duì)某一消息如何處理。靜態(tài)聯(lián)編具有執(zhí)行速度快的優(yōu)點(diǎn)。在理。靜態(tài)聯(lián)編具有執(zhí)行速度快的優(yōu)點(diǎn)。在C+中的編譯時(shí)多態(tài)性中的編譯時(shí)多態(tài)性是通過函數(shù)重載和運(yùn)算符重載實(shí)現(xiàn)的。是通過函數(shù)重載和運(yùn)算符重載實(shí)現(xiàn)的。(2)運(yùn)行時(shí)多態(tài)性運(yùn)行時(shí)多態(tài)性-動(dòng)態(tài)聯(lián)編動(dòng)態(tài)聯(lián)編(連接連接) 系統(tǒng)在運(yùn)行時(shí)動(dòng)態(tài)實(shí)現(xiàn)某一動(dòng)作,即對(duì)某一消息在運(yùn)行過程系統(tǒng)在運(yùn)行時(shí)動(dòng)態(tài)實(shí)現(xiàn)某一動(dòng)作,即對(duì)某一消息在運(yùn)行過程中才確定其如何響應(yīng)。動(dòng)態(tài)聯(lián)編為系統(tǒng)提供了靈活和高度問題抽中才確定其如何響應(yīng)。動(dòng)態(tài)
6、聯(lián)編為系統(tǒng)提供了靈活和高度問題抽象的優(yōu)點(diǎn)。在象的優(yōu)點(diǎn)。在C+中的運(yùn)行時(shí)多態(tài)性是通過繼承和虛函數(shù)實(shí)現(xiàn)的。中的運(yùn)行時(shí)多態(tài)性是通過繼承和虛函數(shù)實(shí)現(xiàn)的。例如:求圖形的面積例如:求圖形的面積類:類:shape操作:求面積操作:求面積類:圓類:圓操作:求面積操作:求面積類:長方形類:長方形操作:求面積操作:求面積解決的方法:用解決的方法:用靜態(tài)聯(lián)編和動(dòng)態(tài)綁定實(shí)現(xiàn)靜態(tài)聯(lián)編和動(dòng)態(tài)綁定實(shí)現(xiàn)例例6.1.1 函數(shù)重載具有編譯時(shí)多態(tài)性函數(shù)重載具有編譯時(shí)多態(tài)性#include class A public: void print( ) cout A; ; class B:public A /定義派生類定義派生類 pub
7、lic: void print( ) cout B; ; /函數(shù)重新定義函數(shù)重新定義void main( ) A a; B b; a.print( ); /訪問基類函數(shù)訪問基類函數(shù) b.print( ); /訪問派生類函數(shù),實(shí)現(xiàn)了多態(tài)訪問派生類函數(shù),實(shí)現(xiàn)了多態(tài) 運(yùn)行結(jié)果:AB6.2 虛函數(shù)虛函數(shù)1.虛函數(shù)的意義虛函數(shù)的意義(1)回顧:基類與派生類對(duì)象的賦值相容回顧:基類與派生類對(duì)象的賦值相容 第一、派生類對(duì)象可以賦值給基類對(duì)象。第一、派生類對(duì)象可以賦值給基類對(duì)象。 第二、派生類對(duì)象的地址可以賦值給指向基類的指針。第二、派生類對(duì)象的地址可以賦值給指向基類的指針。 第三、派生類對(duì)象可以作為基類對(duì)象
8、的引用。第三、派生類對(duì)象可以作為基類對(duì)象的引用。(2)賦值相容問題賦值相容問題 不論采用哪種賦值方式,都只能通過基類對(duì)象不論采用哪種賦值方式,都只能通過基類對(duì)象(或基類或基類對(duì)象的指針或引用對(duì)象的指針或引用)訪問到派生類對(duì)象從基類中繼承到的訪問到派生類對(duì)象從基類中繼承到的成員,不能借此訪問派生類定義的成員。成員,不能借此訪問派生類定義的成員。(3)虛函數(shù)的意義虛函數(shù)的意義 使得通過基類對(duì)象的指針或引用訪問派生類定義的成使得通過基類對(duì)象的指針或引用訪問派生類定義的成員可以實(shí)施。員可以實(shí)施。例6.3 多態(tài)性在人事管理系統(tǒng)中的應(yīng)用/Save as employee.h#ifndef EMPLOYEE
9、_H#define EMPLOYEE_Hclass Employee/雇員,基類Employeepublic:Employee(const char *,const char *);virtual Employee();/析構(gòu)函數(shù)為虛函數(shù)char *getName() const;/讀取姓名char *getID() const;/讀取身份證號(hào)virtual float getSalary() const;/虛函數(shù),讀取工資virtual void print() const;/虛函數(shù),顯示 private:char *Name;/姓名char *ID; ; /身份證號(hào)#endif/Save
10、as employee.cpp#include #include #include employee.hEmployee:Employee(const char *pn,const char *pid)Name=new char strlen(pn)+1;strcpy(Name,pn);ID=new char strlen(pid)+1;strcpy(ID,pid);Employee:Employee()delete Name;delete ID; char *Employee:getName() constreturn Name;/返回指向姓名的指針char *Employee:getID(
11、) constreturn ID; /返回指向身份證號(hào)的指針float Employee:getSalary() constreturn 0.0;/虛函數(shù),形式上的返回,真正的返回值由其派生類實(shí)現(xiàn)void Employee:print() constcoutAn employee! endl;/虛函數(shù),形式上的輸出/Save as manager.h#ifndef MANAGRE_H#define MANAGER_H#include Employee.hclass Manager:public Employee/經(jīng)理,公有繼承public:Manager(const char *,const
12、char *,float =0.0);/姓名,身份證號(hào),工資virtual Manager();void setSalary(float);/設(shè)置工資virtual float getSalary() const;/虛函數(shù),讀取工資virtual void print() const;/虛函數(shù),顯示private:float weeklySalary;/經(jīng)理的周工資;#endif/Save as manager.cpp#include #include employee.h#include manager.hManager:Manager(const char *pn,const char *
13、pid,float s):Employee(pn,pid)/初始化表調(diào)用基類構(gòu)造函數(shù)初始化setSalary(s);/設(shè)置工資Manager:Manager() ;/自動(dòng)執(zhí)行基類析構(gòu)函數(shù)void Manager:setSalary(float s)weeklySalary=s;/設(shè)置工資float Manager:getSalary() constreturn weeklySalary;/真正的返回值void Manager:print() const/經(jīng)理的輸出coutManager: getName()/派生類內(nèi)部訪問基類成員 ; ID: getID()endl; /派生類內(nèi)部訪問基類成員
14、/Save as salesman.h#ifndef SALESMAN_H#define SALESMAN_H#include employee.hclass Salesman:public Employee/銷售人員,公有繼承public:Salesman(const char *,const char *,float =0.0,float =0.0,unsigned =0);virtual Salesman();void setSalary(float);/周基本工資賦值virtual float getSalary() const;/虛函數(shù),讀取工資virtual void print(
15、) const;/虛函數(shù),顯示private:float baseSalary;/周基本工資float commission;/每件銷售傭金unsigned quanlity;/周銷售數(shù);#endif/Save as salesman.cpp#include #include salesman.hSalesman:Salesman(const char *pn,const char *pid,float bs,float c,unsigned q):Employee(pn,pid)/初始化表調(diào)用基類構(gòu)造函數(shù)baseSalary=bs;commission=c;quanlity=q;Salesm
16、an:Salesman() ; /自動(dòng)執(zhí)行基類析構(gòu)函數(shù)void Salesman:setSalary(float bs)baseSalary=bs;/周基本工資賦值float Salesman:getSalary() constreturn (baseSalary+commission*quanlity);/真正的返回void Salesman:print() const/銷售員輸出coutSalesman: getName()/派生類內(nèi)部訪問基類成員; ID: getID()endl;/派生類內(nèi)部訪問基類成員/Save as main.cpp#include #include manager
17、.h#include salesman.hvoid main()Employee *ptr;/定義Employee類的指針Manager m(Zhang Hua,320103820920201,1500.0);Salesman sm(Yang Hong,310105770411202,300.0,9.5,95);ptr=&m; /ptr指向經(jīng)理,動(dòng)態(tài)綁定ptr-print();/print()為虛函數(shù),輸出經(jīng)理信息而不是An employee! coutEarnings per week: getSalary()endl;/通過指針實(shí)現(xiàn)多態(tài)coutEarnings per week:
18、m.getSalary()endl;/通過對(duì)象變量實(shí)現(xiàn)coutprint(); /print()為虛函數(shù),輸出銷售員信息,而不是An employeecoutEarnings per week: getSalary()endl;/動(dòng)態(tài)聯(lián)編coutEarnings per week: sm.getSalary()endl;/靜態(tài)聯(lián)編運(yùn)行結(jié)果:運(yùn)行結(jié)果:說明:說明:(1)可只在基類的成員函數(shù)前加可只在基類的成員函數(shù)前加 virtual, 在派生類中不加在派生類中不加, 但為了便于閱讀但為了便于閱讀, 可在所有要聲明為虛函數(shù)的前面都加可在所有要聲明為虛函數(shù)的前面都加 virtual。(2)只需要在類
19、定義文件只需要在類定義文件, 即頭文件中的虛函數(shù)前加即頭文件中的虛函數(shù)前加virtual, 在在cpp文件中就不要再加文件中就不要再加virtual。(3)通過指向派生類對(duì)象的基類指針訪問成員函數(shù)時(shí),非通過指向派生類對(duì)象的基類指針訪問成員函數(shù)時(shí),非虛函數(shù)由指針類型決定調(diào)用的函數(shù)版本;虛函數(shù)由指針虛函數(shù)由指針類型決定調(diào)用的函數(shù)版本;虛函數(shù)由指針指向的實(shí)際對(duì)象決定調(diào)用的函數(shù)版本。指向的實(shí)際對(duì)象決定調(diào)用的函數(shù)版本。4.虛函數(shù)的特性虛函數(shù)的特性(1)一旦將某個(gè)成員函數(shù)聲明為虛函數(shù)后,它在繼承體系一旦將某個(gè)成員函數(shù)聲明為虛函數(shù)后,它在繼承體系中將永遠(yuǎn)為虛函數(shù)。中將永遠(yuǎn)為虛函數(shù)。(2)如果基類定義了虛函數(shù)
20、,當(dāng)通過基類指針或引用調(diào)用如果基類定義了虛函數(shù),當(dāng)通過基類指針或引用調(diào)用派生類對(duì)象時(shí),將訪問到它們實(shí)際所指對(duì)象中的虛函數(shù)派生類對(duì)象時(shí),將訪問到它們實(shí)際所指對(duì)象中的虛函數(shù)版本。版本。(3)只有通過基類對(duì)象的指針和引用訪問派生類對(duì)象的虛只有通過基類對(duì)象的指針和引用訪問派生類對(duì)象的虛函數(shù)時(shí),才能體現(xiàn)動(dòng)態(tài)多態(tài)性。函數(shù)時(shí),才能體現(xiàn)動(dòng)態(tài)多態(tài)性。(4)派生類中的虛函數(shù)要保持其虛特征,必須與基類虛函派生類中的虛函數(shù)要保持其虛特征,必須與基類虛函數(shù)的函數(shù)原型完全相同,否則就是普通的重載函數(shù),與數(shù)的函數(shù)原型完全相同,否則就是普通的重載函數(shù),與基類的虛函數(shù)無關(guān)?;惖奶摵瘮?shù)無關(guān)。例例6.4 基類基類base和派生類
21、和派生類derive都有成員函數(shù)都有成員函數(shù)f2(),但它們的參,但它們的參數(shù)不同,因此不能體現(xiàn)成員函數(shù)數(shù)不同,因此不能體現(xiàn)成員函數(shù)f2()在派生類在派生類derive中的虛函數(shù)中的虛函數(shù)特性。特性。#include class base public: virtual void f1( ) cout f1 function of base n ; /定義虛函數(shù)定義虛函數(shù) virtual void f2( ) cout f2 function of base n ; /定義虛函數(shù)定義虛函數(shù) void f3( ) cout f3 function of base n ; /定義一般函數(shù)定義一般函
22、數(shù) ; class derive: public base public: void f1( ) cout f1 function of derive n ; /重新定義虛函數(shù)重新定義虛函數(shù) void f2(int x ) cout f2 function of derive n ; /重新定義虛函數(shù),重新定義虛函數(shù), /由于形式改變,失去虛函數(shù)功能由于形式改變,失去虛函數(shù)功能 void f3( ) cout f1( ); /調(diào)基類函數(shù)調(diào)基類函數(shù) ptr-f2( ); /調(diào)基類函數(shù)調(diào)基類函數(shù) ptr-f3( ); /調(diào)基類函數(shù)調(diào)基類函數(shù) rD.f1( ); /調(diào)派生類函數(shù)調(diào)派生類函數(shù),多態(tài)性多
23、態(tài)性 rD.f2( ); /調(diào)基類函數(shù)調(diào)基類函數(shù),由于由于f2的形式改變,不具多態(tài)性的形式改變,不具多態(tài)性 rD.f3( ); /調(diào)基類函數(shù)調(diào)基類函數(shù),由于沒有聲明為虛函數(shù),不具多態(tài)性由于沒有聲明為虛函數(shù),不具多態(tài)性結(jié)果結(jié)果: f1 function of base f2 function of base f3 function of base f1 function of derive f2 function of base f3 function of base(5)派生類對(duì)象通過從基類繼承的成員函數(shù)調(diào)用虛函數(shù)時(shí),將訪派生類對(duì)象通過從基類繼承的成員函數(shù)調(diào)用虛函數(shù)時(shí),將訪問到派生類中的版本。
24、如:派生類問到派生類中的版本。如:派生類D的對(duì)象通過繼承到的基類的對(duì)象通過繼承到的基類B的成員函數(shù)的成員函數(shù)f()將訪問到派生類將訪問到派生類D中的虛函數(shù)中的虛函數(shù)g()。#include class Bpublic: void f() g(); virtual void g() cout B:g; ;class D : public Bpublic: void g() cout D:g; ;void main() D d; d.f(); 運(yùn)行結(jié)果運(yùn)行結(jié)果: D:g(6)只有類的非靜態(tài)成員函數(shù)才能被定義為虛函數(shù),類的構(gòu)造函只有類的非靜態(tài)成員函數(shù)才能被定義為虛函數(shù),類的構(gòu)造函數(shù)和靜態(tài)成員函數(shù)不能
25、定義為虛函數(shù)。因?yàn)樘摵瘮?shù)在繼承層次數(shù)和靜態(tài)成員函數(shù)不能定義為虛函數(shù)。因?yàn)樘摵瘮?shù)在繼承層次結(jié)構(gòu)中才能夠發(fā)生作用,而構(gòu)造函數(shù)、靜態(tài)成員是不能夠被繼結(jié)構(gòu)中才能夠發(fā)生作用,而構(gòu)造函數(shù)、靜態(tài)成員是不能夠被繼承的。承的。(7)內(nèi)聯(lián)函數(shù)也不能定義為虛函數(shù)。因?yàn)閮?nèi)聯(lián)函數(shù)采用的是靜態(tài)內(nèi)聯(lián)函數(shù)也不能定義為虛函數(shù)。因?yàn)閮?nèi)聯(lián)函數(shù)采用的是靜態(tài)聯(lián)編的方式,而虛函數(shù)是在程序運(yùn)行時(shí)才與具體函數(shù)動(dòng)態(tài)綁定聯(lián)編的方式,而虛函數(shù)是在程序運(yùn)行時(shí)才與具體函數(shù)動(dòng)態(tài)綁定的,采用的是動(dòng)態(tài)聯(lián)編的方式,即使虛函數(shù)在類體內(nèi)被定義,的,采用的是動(dòng)態(tài)聯(lián)編的方式,即使虛函數(shù)在類體內(nèi)被定義,C+編譯器也將它視為非內(nèi)聯(lián)函數(shù)。編譯器也將它視為非內(nèi)聯(lián)函數(shù)。5.虛
26、析構(gòu)函數(shù)虛析構(gòu)函數(shù) 基類析構(gòu)函數(shù)幾乎總是為虛析構(gòu)函數(shù)。假定使用基類析構(gòu)函數(shù)幾乎總是為虛析構(gòu)函數(shù)。假定使用delete和一和一個(gè)指向派生類的基類指針來銷毀派生類對(duì)象,如果基類析構(gòu)函個(gè)指向派生類的基類指針來銷毀派生類對(duì)象,如果基類析構(gòu)函數(shù)不為虛數(shù)不為虛, 是一個(gè)普通成員函數(shù),則在通過基類對(duì)象的引用或是一個(gè)普通成員函數(shù),則在通過基類對(duì)象的引用或指針對(duì)派生類對(duì)象析構(gòu)時(shí)將調(diào)用到基類析構(gòu)函數(shù),致使派生類指針對(duì)派生類對(duì)象析構(gòu)時(shí)將調(diào)用到基類析構(gòu)函數(shù),致使派生類對(duì)象析構(gòu)不徹底!對(duì)象析構(gòu)不徹底!例:在非虛析構(gòu)函數(shù)的情況下,通過基類指針對(duì)派生對(duì)象的析例:在非虛析構(gòu)函數(shù)的情況下,通過基類指針對(duì)派生對(duì)象的析構(gòu)不徹底。構(gòu)
27、不徹底。#include class Apublic: A() coutcall A:A()endl; ;/析構(gòu)函數(shù)非虛析構(gòu)函數(shù)非虛class B:public A char *buf;public: B(int i)buf=new chari; B() delete buf; coutcall B:B()endl; ;void main() A* a=new B(10); delete a; 運(yùn)行結(jié)果運(yùn)行結(jié)果: call A:A()此結(jié)果表明沒有此結(jié)果表明沒有析構(gòu)析構(gòu)buf。例:在虛析構(gòu)函數(shù)的情況下,通過基類指針對(duì)派生對(duì)象的析構(gòu)例:在虛析構(gòu)函數(shù)的情況下,通過基類指針對(duì)派生對(duì)象的析構(gòu)是徹底的。
28、是徹底的。#include class Apublic: virtual A() cout“call A:A()”endl; ;/析構(gòu)函數(shù)為虛析構(gòu)函數(shù)為虛class B:public A char *buf;public: B(int i)buf=new chari; B() delete buf; coutcall B:B()endl; ;void main() A* a=new B(10); delete a; 運(yùn)行結(jié)果運(yùn)行結(jié)果: call B:B()call A:A()此結(jié)果表明析構(gòu)此結(jié)果表明析構(gòu)了了buf。6.多重繼承中的多態(tài)性多重繼承中的多態(tài)性 對(duì)于多重派生類,其多態(tài)性又將如何傳遞呢
29、?請(qǐng)看下面例對(duì)于多重派生類,其多態(tài)性又將如何傳遞呢?請(qǐng)看下面例子。子。base1, 有虛函數(shù)有虛函數(shù)bdderive,有多態(tài)性有多態(tài)性bderive,有多態(tài)性有多態(tài)性bbderive:base1對(duì)象調(diào)用對(duì)象調(diào)用: 有多態(tài)性有多態(tài)性base2對(duì)象調(diào)用對(duì)象調(diào)用: 無多態(tài)性無多態(tài)性base2,無虛函數(shù)無虛函數(shù)例例6.5 多繼承關(guān)系中的多態(tài)性多繼承關(guān)系中的多態(tài)性#includeclass base1 /定義基類定義基類 base1public: virtual void f( ) cout base1 n; ; /定義虛函數(shù)定義虛函數(shù)class base2 /定義基類定義基類 base2 public
30、: void f( ) cout base2 n ; ; /定義一般函數(shù)定義一般函數(shù)class bderive: public base1 /定義定義base1 的派生類的派生類public: virtual void f( ) cout bderive n ; ; /重新定義虛函數(shù)重新定義虛函數(shù)class bdderive: public bderive /定義派生類定義派生類bderive的派生類的派生類 bdderivepublic: virtual void f( ) cout bdderive n ; ; /重新定義虛函數(shù)重新定義虛函數(shù)class bbderive: public b
31、ase1, public base2 /定義基類定義基類 base1 和和 base2的派生類的派生類 public: virtual void f( ) cout f( ); /調(diào)調(diào)base1基類函數(shù)基類函數(shù) p1=&bbd; p1-f( ); /調(diào)派生類函數(shù)調(diào)派生類函數(shù),多態(tài)性多態(tài)性 p2=&bbd; p2-f( ); /調(diào)調(diào)base2基類函數(shù)基類函數(shù),無多態(tài)性無多態(tài)性 p1=&bdd; p1-f( ); /調(diào)派生類函數(shù)調(diào)派生類函數(shù),有多態(tài)性有多態(tài)性 運(yùn)行結(jié)果運(yùn)行結(jié)果: base1 bbderive base2 bddrive說明:說明: 在多重繼承中,若某一基類無
32、虛函數(shù)定義,則由在多重繼承中,若某一基類無虛函數(shù)定義,則由該基類派生類的對(duì)象不具有多態(tài)性。該基類派生類的對(duì)象不具有多態(tài)性。 base2 *p2; /基類基類 base2中沒有定義中沒有定義 f( )為虛函數(shù)為虛函數(shù) p2=&bbd; p2-f( ); /調(diào)基類函數(shù)調(diào)基類函數(shù), 無多態(tài)性無多態(tài)性6.3 純虛函數(shù)和抽象類純虛函數(shù)和抽象類1.純虛函數(shù)純虛函數(shù) 在在C中,僅為多態(tài)機(jī)制提供接口中,僅為多態(tài)機(jī)制提供接口(占用一個(gè)位置占用一個(gè)位置)而沒有而沒有任何實(shí)體定義的函數(shù)。任何實(shí)體定義的函數(shù)。 純虛函數(shù)只給出函數(shù)聲明,不給出具體實(shí)現(xiàn)內(nèi)容,同時(shí)在純虛函數(shù)只給出函數(shù)聲明,不給出具體實(shí)現(xiàn)內(nèi)容,同時(shí)在
33、聲明函數(shù)原型之后須賦聲明函數(shù)原型之后須賦“0”值。其一般形式為:值。其一般形式為:如:如:class X virtual type functionname(parameters) = 0; ; 純虛函數(shù)一般在基類中定義,在派生類中重載。純虛函數(shù)一般在基類中定義,在派生類中重載。2.抽象類抽象類 其中至少包含了一個(gè)純虛函數(shù)的類稱為抽象類。且規(guī)定:其中至少包含了一個(gè)純虛函數(shù)的類稱為抽象類。且規(guī)定:(1)由于純虛函數(shù)沒有實(shí)現(xiàn)代碼,抽象類不能生成對(duì)象。由于純虛函數(shù)沒有實(shí)現(xiàn)代碼,抽象類不能生成對(duì)象。(2)抽象類不能作為參數(shù)的類型。抽象類不能作為參數(shù)的類型。(3)抽象類僅能作為基類,從而可聲明指針或引用
34、抽象類僅能作為基類,從而可聲明指針或引用, 通過抽象通過抽象類的指針或引用訪問到它的派生類的成員函數(shù),實(shí)現(xiàn)運(yùn)行時(shí)類的指針或引用訪問到它的派生類的成員函數(shù),實(shí)現(xiàn)運(yùn)行時(shí)的多態(tài)性。的多態(tài)性。(4)如果派生類只是簡單地繼承了抽象類的純虛函數(shù),而沒有如果派生類只是簡單地繼承了抽象類的純虛函數(shù),而沒有重新定義基類的純虛函數(shù),則派生類也是一個(gè)抽象類。重新定義基類的純虛函數(shù),則派生類也是一個(gè)抽象類。例例6.6 多態(tài)性的應(yīng)用多態(tài)性的應(yīng)用: 計(jì)算圖形面積,其中計(jì)算圖形面積,其中shape為一般有關(guān)圖為一般有關(guān)圖形的特征描述,是基類。類形的特征描述,是基類。類circle代表代表“圓圓”, square代表代表“正方形正方形”。如下圖所示。如下圖所示。shape:虛函數(shù):虛函數(shù)area( )square:area( ): 多態(tài)多態(tài)circle: area( ): 多態(tài)多態(tài)/Save as shape.h#ifndef SHAPE_H#define SHAPE_Hclass shapepublic:virtual float area() const =0; /聲明純虛函數(shù)聲明純虛函數(shù)virtual void print(
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度房產(chǎn)繼承公積金貸款買賣合同4篇
- 2025年校長聘任合同:聚焦核心素養(yǎng)培養(yǎng)合作框架3篇
- 2025-2030年中國麥芽糊精行業(yè)發(fā)展現(xiàn)狀及前景趨勢(shì)分析報(bào)告
- 2025-2030年中國鑄鐵鍋市場運(yùn)營狀況與發(fā)展?jié)摿Ψ治鰣?bào)告
- 2025-2030年中國酸奶發(fā)酵劑行業(yè)市場前景趨勢(shì)與投資潛力分析報(bào)告
- 2025年度煤炭鐵路運(yùn)輸供應(yīng)鏈金融服務(wù)合同3篇
- 2025年相鄰?fù)恋赝恋亓鬓D(zhuǎn)稅收優(yōu)惠政策協(xié)議3篇
- 2025-2030年中國觸摸屏玻璃基板行業(yè)市場運(yùn)行狀況及發(fā)展趨勢(shì)預(yù)測(cè)報(bào)告
- 2025-2030年中國螺絲刀行業(yè)市場發(fā)展現(xiàn)狀及前景規(guī)劃研究報(bào)告
- 二零二五年度戶外廣告位臨時(shí)租賃合同示范文本4篇
- 工程管理重大風(fēng)險(xiǎn)應(yīng)對(duì)方案
- 直播帶貨助農(nóng)現(xiàn)狀及發(fā)展對(duì)策研究-以抖音直播為例(開題)
- 腰椎間盤突出疑難病例討論
- 《光伏發(fā)電工程工程量清單計(jì)價(jià)規(guī)范》
- 2023-2024學(xué)年度人教版四年級(jí)語文上冊(cè)寒假作業(yè)
- (完整版)保證藥品信息來源合法、真實(shí)、安全的管理措施、情況說明及相關(guān)證明
- 營銷專員績效考核指標(biāo)
- 陜西麟游風(fēng)電吊裝方案專家論證版
- 供應(yīng)商審核培訓(xùn)教程
- 【盒馬鮮生生鮮類產(chǎn)品配送服務(wù)問題及優(yōu)化建議分析10000字(論文)】
- 肝硬化心衰患者的護(hù)理查房課件
評(píng)論
0/150
提交評(píng)論