




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、第九章鄭偉鄭偉C+ 6- 1 第九章第九章 多態(tài)多態(tài)C+ 6- 2 9.1 多態(tài)性的概念多態(tài)性的概念9.2 重載、覆蓋與靜態(tài)聯(lián)編重載、覆蓋與靜態(tài)聯(lián)編9.3 虛函數(shù)與運(yùn)行時(shí)多態(tài)虛函數(shù)與運(yùn)行時(shí)多態(tài)9.4 純虛函數(shù)與抽象類純虛函數(shù)與抽象類9.5 模板模板C+ 6- 3 9.1 多態(tài)性的概念多態(tài)性的概念多態(tài)性多態(tài)性( polymorphism ) 是面向?qū)ο蟪绦蛟O(shè)計(jì)的重要是面向?qū)ο蟪绦蛟O(shè)計(jì)的重要特征。特征。C+支持多態(tài)性,利用多態(tài)性,可以設(shè)計(jì)和擴(kuò)展一個(gè)支持多態(tài)性,利用多態(tài)性,可以設(shè)計(jì)和擴(kuò)展一個(gè)易于擴(kuò)展的系統(tǒng)。易于擴(kuò)展的系統(tǒng)。l什么叫多態(tài)?什么叫多態(tài)?u多態(tài)的意思是一種事物的多種形態(tài)。多態(tài)的意思是一種事
2、物的多種形態(tài)。u在在C+中,中,是指具有不同功能的函數(shù)可以用同一個(gè)函數(shù)名是指具有不同功能的函數(shù)可以用同一個(gè)函數(shù)名。u面向?qū)ο蠓椒ㄖ幸话闶沁@樣描述多態(tài)性的:向不同的對象面向?qū)ο蠓椒ㄖ幸话闶沁@樣描述多態(tài)性的:向不同的對象發(fā)送同一個(gè)消息,不同的對象在接收時(shí)會產(chǎn)生不同的行為發(fā)送同一個(gè)消息,不同的對象在接收時(shí)會產(chǎn)生不同的行為(即方法)。(即方法)。C+ 6- 4 9.1.1 面向?qū)ο蟪绦蛟O(shè)計(jì)中的多態(tài)面向?qū)ο蟪绦蛟O(shè)計(jì)中的多態(tài)我們其實(shí)已經(jīng)接觸過多態(tài)性的現(xiàn)象。如函數(shù)的重載,我們其實(shí)已經(jīng)接觸過多態(tài)性的現(xiàn)象。如函數(shù)的重載,運(yùn)算符的重載。運(yùn)算符的重載。l多態(tài)性分類多態(tài)性分類:從系統(tǒng)實(shí)現(xiàn)的角度看,多態(tài)性分為以下兩類:
3、從系統(tǒng)實(shí)現(xiàn)的角度看,多態(tài)性分為以下兩類:u靜態(tài)多態(tài)性:又稱編譯時(shí)的多態(tài)性。如函數(shù)重載和運(yùn)算符靜態(tài)多態(tài)性:又稱編譯時(shí)的多態(tài)性。如函數(shù)重載和運(yùn)算符重載,都屬于靜態(tài)多態(tài)性。重載,都屬于靜態(tài)多態(tài)性。u動態(tài)多態(tài)性:有稱為運(yùn)行時(shí)的多態(tài)性。它主要表現(xiàn)為虛函動態(tài)多態(tài)性:有稱為運(yùn)行時(shí)的多態(tài)性。它主要表現(xiàn)為虛函數(shù)數(shù)( virtual function )。C+ 6- 5 9.1.1 面向?qū)ο蟪绦蛟O(shè)計(jì)中的多態(tài)面向?qū)ο蟪绦蛟O(shè)計(jì)中的多態(tài)l面向?qū)ο蟮亩鄳B(tài)可以分為四類:面向?qū)ο蟮亩鄳B(tài)可以分為四類: (1)重載多態(tài))重載多態(tài) (2)強(qiáng)制多態(tài))強(qiáng)制多態(tài) (3)包含多態(tài)(或運(yùn)行(時(shí))多態(tài))包含多態(tài)(或運(yùn)行(時(shí))多態(tài))(4)參數(shù)多
4、態(tài))參數(shù)多態(tài) l普通函數(shù)及類的成員函數(shù)重載、運(yùn)算符重載屬于重載多態(tài)普通函數(shù)及類的成員函數(shù)重載、運(yùn)算符重載屬于重載多態(tài)l類型強(qiáng)制轉(zhuǎn)換屬于強(qiáng)制多態(tài)類型強(qiáng)制轉(zhuǎn)換屬于強(qiáng)制多態(tài) l虛函數(shù)屬于包含多態(tài)虛函數(shù)屬于包含多態(tài) l函數(shù)模板和類模板屬于參數(shù)多態(tài)函數(shù)模板和類模板屬于參數(shù)多態(tài)C+ 6- 6 9.1.2 多態(tài)性的實(shí)現(xiàn)多態(tài)性的實(shí)現(xiàn)聯(lián)編聯(lián)編l主程序在調(diào)用子程序之前,一般要:保存現(xiàn)場拿到子程序的地址轉(zhuǎn)向子程序執(zhí)行。l在C + 中,普通的函數(shù)調(diào)用由C + 鏈接器在鏈接過程中將子程序(被調(diào)函數(shù))的內(nèi)存(邏輯)地址放到主程序(主調(diào)函數(shù))的代碼中。l如果主程序調(diào)用子程序的語句是多態(tài)性語句,那么在執(zhí)行調(diào)用之前,主程序必須
5、得確定子程序的地址(或者說,確定調(diào)用哪個(gè)子程序),這個(gè)過程稱為聯(lián)編(Binding),也可翻譯成“綁定”。C+ 6- 7 9.1.2 多態(tài)性的實(shí)現(xiàn)多態(tài)性的實(shí)現(xiàn)聯(lián)編聯(lián)編l聯(lián)編有兩種方式:靜態(tài)聯(lián)編和動態(tài)聯(lián)編。(1)在源程序編譯的時(shí)候就能確定具有多態(tài)性的語句調(diào)用哪個(gè)函數(shù),稱為靜態(tài)聯(lián)編。函數(shù)重載和模板都是在編譯時(shí)確定被調(diào)函數(shù),所以屬于靜態(tài)聯(lián)編。(2)在程序運(yùn)行時(shí)才能夠確定具有多態(tài)性的語句究竟調(diào)用哪個(gè)函數(shù),稱為動態(tài)聯(lián)編。用動態(tài)聯(lián)編實(shí)現(xiàn)的多態(tài),也稱為運(yùn)行時(shí)多態(tài)(Runtime Polymorphism)。l聯(lián)編與多態(tài)之間的關(guān)系可以用圖9-1 簡明地描述。C+ 6- 8 9.2 重載、覆蓋與靜態(tài)聯(lián)編重載、覆
6、蓋與靜態(tài)聯(lián)編9.2.1 重載與靜態(tài)聯(lián)編重載與靜態(tài)聯(lián)編以下是一個(gè)重載函數(shù)的例子。int add(int a)return a+10;int add(int a,int b)return a+b;int main()int x=1,y=2;add(x);add(x,y);return 0;l上述代碼中有兩個(gè)重載函數(shù)add(),在main()函數(shù)中調(diào)用了這兩個(gè)重載函數(shù)。編譯器根據(jù)函數(shù)的參數(shù)能夠確定每次調(diào)用哪個(gè)函數(shù),而每個(gè)函數(shù)都有自己的地址,編譯器只要加上轉(zhuǎn)移到相應(yīng)地址的“轉(zhuǎn)移指令”,就可以完成對不同重載函數(shù)的調(diào)用。l由此可見,所謂的“同名”僅僅是C + 的特性,經(jīng)過編譯器處理之后,同名的函數(shù)變成了不
7、同地址的子程序,對同名函數(shù)的調(diào)用變成了對不同地址子程序的調(diào)用。這個(gè)轉(zhuǎn)變過程是由編譯器完成的,換句話說,編編譯器分辨出了同名函數(shù)的不同之處譯器分辨出了同名函數(shù)的不同之處。這屬于靜態(tài)聯(lián)編。C+ 6- 9 9.2 重載、覆蓋與靜態(tài)聯(lián)編重載、覆蓋與靜態(tài)聯(lián)編9.2.1 覆蓋與靜態(tài)聯(lián)編覆蓋與靜態(tài)聯(lián)編l覆蓋現(xiàn)象只能出現(xiàn)在繼承樹中。在派生類中定義和基類中同名的成員函數(shù),是對基類進(jìn)行改造,為派生類增加新行為的一種常用的方法。通過不同的派生類的對象(對象指針或者對象引用),調(diào)用這些同名的成員函數(shù),實(shí)現(xiàn)不同的操作,也是多態(tài)性的一種表現(xiàn)。l在某些情況下,覆蓋會導(dǎo)致靜態(tài)聯(lián)編;而另外一些情況下,則會導(dǎo)致動態(tài)聯(lián)編。C+ 6
8、- 10 9.2 重載、覆蓋與靜態(tài)聯(lián)編重載、覆蓋與靜態(tài)聯(lián)編9.2.1 覆蓋與靜態(tài)聯(lián)編覆蓋與靜態(tài)聯(lián)編l例9-19-1 用對象訪問繼承樹中的同名函數(shù)。/以下代碼僅為示例,無法編譯class B public: f().; /基類class P: public B public: f().; /派生類1class Q: public B public: f().; /派生類2main () P p; Q q; /創(chuàng)建派生類對象p.f(); /調(diào)用P:f()q.f(); /調(diào)用Q:f()l基類B 派生出類P 和類Q,這3 個(gè)類中都有同名函數(shù)f()。在類的外部,通過派生類的對象調(diào)用同名函數(shù),那么該調(diào)用被
9、編譯器在編譯階段鏈接到該對象所屬類的同名函數(shù)上。這種情況下,編譯器執(zhí)行了靜態(tài)聯(lián)編。l通過對象調(diào)用類的同名函數(shù),一定是本類通過對象調(diào)用類的同名函數(shù),一定是本類中的函數(shù)。中的函數(shù)。C+ 6- 11 9.2 重載、覆蓋與靜態(tài)聯(lián)編重載、覆蓋與靜態(tài)聯(lián)編9.2.1 覆蓋與靜態(tài)聯(lián)編覆蓋與靜態(tài)聯(lián)編例9-29-2 用指針訪問繼承樹中的同名函數(shù)。/以下代碼僅為示例,無法編譯class B public: f(). ; /基類class P: public B public: f(). ; /派生類1class Q: public B public: f(). ; /派生類2main () B* b_ptr; P
10、p; Q q; /定義基類的指針和派生類的對象b_ptr=&p; /基類指針指向派生類b_ptr-f(); /通過基類指針調(diào)用B:f()b_ptr=&q; /基類指針指向派生類b_ptr-f(); /通過基類指針調(diào)用B:f()l基類B 派生出類P 和類Q,這3 個(gè)類中都有同名函數(shù)f()。在類的外部,用派生類對象的地址為派生類對象的地址為基類指針賦值,隨后,基類指針賦值,隨后,使用該基類指針調(diào)用同使用該基類指針調(diào)用同名函數(shù)。此時(shí)所調(diào)用的名函數(shù)。此時(shí)所調(diào)用的同名函數(shù)是基類的同名同名函數(shù)是基類的同名函數(shù)。函數(shù)。原因在于,用派生類對象的地址為基類指針賦值時(shí),實(shí)際上進(jìn)行了派生類對象向基類
11、對象的轉(zhuǎn)換(參見8.4.2 小節(jié))。上述情況下,編譯器也執(zhí)行了靜態(tài)聯(lián)編。C+ 6- 12 9.2.3 一個(gè)典型的例子一個(gè)典型的例子現(xiàn)在來看一個(gè)綜合性的示例,請同學(xué)們認(rèn)真讀懂這個(gè)現(xiàn)在來看一個(gè)綜合性的示例,請同學(xué)們認(rèn)真讀懂這個(gè)程序。程序。我們先建立一個(gè)我們先建立一個(gè)point ( 點(diǎn)點(diǎn) )類,包含數(shù)據(jù)成員類,包含數(shù)據(jù)成員x,y ( 坐坐標(biāo)點(diǎn)標(biāo)點(diǎn) )。以它為基類,派生出一個(gè)。以它為基類,派生出一個(gè)circle ( 圓圓 )類,增加數(shù)據(jù)類,增加數(shù)據(jù)成員成員 r (半徑)。再以(半徑)。再以circle 類為直接基類,派生出一個(gè)類為直接基類,派生出一個(gè)cylinder ( 圓柱體圓柱體 )類,增加數(shù)據(jù)成
12、員類,增加數(shù)據(jù)成員 h ( 高高 )。要求重載運(yùn)。要求重載運(yùn)算符算符“”,使之能輸出這些對象。,使之能輸出這些對象。這個(gè)題目程序較長,我們分為若干步驟進(jìn)行,分步調(diào)這個(gè)題目程序較長,我們分為若干步驟進(jìn)行,分步調(diào)試:試:u先聲明基類先聲明基類point類,并調(diào)試之;類,并調(diào)試之;u再聲明派生類再聲明派生類circle類,調(diào)試之;類,調(diào)試之;最后聲明最后聲明cylinder類,調(diào)試之。類,調(diào)試之。C+ 6- 13 先聲明基類先聲明基類point#include using namespace std;class point /聲明類聲明類pointpublic: point (float x=0,
13、float y=0 ); /有默認(rèn)值的構(gòu)造函數(shù)有默認(rèn)值的構(gòu)造函數(shù) void setPoint (float, float); /設(shè)置點(diǎn)坐標(biāo)設(shè)置點(diǎn)坐標(biāo) float getX ( ) const return x; / 讀讀x 值值 float getY ( ) const return y; / 讀讀y 值值 friend ostream & operator ( ostream &, const point &);protected: float x,y;/ 下面定義下面定義 point類的成員函數(shù)類的成員函數(shù)point : point (float a, float
14、b) / point的構(gòu)造函數(shù)的構(gòu)造函數(shù) x = a; y = b; void point : setPoint (float a, float b) x =a; y = b; ostream &operator (ostream &output, const point &p) / 重載運(yùn)算符重載運(yùn)算符 output“x=“p.x“, y=“p.y“”endl; return output; 編寫好左邊程編寫好左邊程序后,可調(diào)試它的序后,可調(diào)試它的正確性。我們編寫正確性。我們編寫一個(gè)臨時(shí)的一個(gè)臨時(shí)的main函數(shù):函數(shù):Void main( ) point p(1.1,
15、2.2); coutpendl; p.setPoint(3.3,4.4); coutpendl; 運(yùn)行通過后,運(yùn)行通過后,刪除臨時(shí)的刪除臨時(shí)的main函數(shù),進(jìn)入下一步函數(shù),進(jìn)入下一步工作。工作。C+ 6- 14 再聲明派生類再聲明派生類circle類類class circle : public point /聲明類聲明類citclepublic: circle (float x=0, float y=0, float r=0); /構(gòu)造函數(shù)構(gòu)造函數(shù) void setRadius ( float); /設(shè)置圓半徑設(shè)置圓半徑 float getRadius ( ) const return rad
16、ius; / 讀讀 r值值 float area ( ) const; / 計(jì)算圓面積計(jì)算圓面積 friend ostream & operator ( ostream &, const circle &);protected: float radius;/ 下面定義下面定義 circle類的成員函數(shù)類的成員函數(shù)circle : circle (float a, float b, float r) : point (a,b),radius(r) / point的構(gòu)造函數(shù)的構(gòu)造函數(shù)void circle : setRadius (float r) radius = r;
17、float circle : area( ) const / 計(jì)算圓面積計(jì)算圓面積 return 3.14159*radius*radius; ostream &operator (ostream &output, const circle &c) / 重載運(yùn)算符重載運(yùn)算符 output“x=“c.x“, y=“c.y“, r=” c.radius“, area=“c.area( )endl; return output; 編寫好左邊程編寫好左邊程序后,可調(diào)試它的序后,可調(diào)試它的正確性。我們編寫正確性。我們編寫一個(gè)臨時(shí)的一個(gè)臨時(shí)的main函函數(shù):數(shù):Void main(
18、 ) circle c(1.1,2.2,1.0); c.setRadius(2.0); c.setPoint(2.0, 2.0 ); coutcendl; 運(yùn)行通過后,運(yùn)行通過后,刪除臨時(shí)的刪除臨時(shí)的main函函數(shù),進(jìn)入下一步工數(shù),進(jìn)入下一步工作。作。C+ 6- 15 最后聲明最后聲明cylinder類類class cylinder : public circle /聲明類聲明類cylinderpublic: cylinder (float x=0, float y=0, float r=0, float h=0 ); /構(gòu)造函數(shù)構(gòu)造函數(shù) void setHeight ( float h) h
19、eight = h; /設(shè)置圓柱體高設(shè)置圓柱體高 float getHeight ( ) const return height; / 讀讀 r值值 float area ( ) const; / 計(jì)算圓柱表面積計(jì)算圓柱表面積 float volume ( ) const; /求體積求體積 friend ostream & operator ( ostream &, const cylinder &);protected: float height;/ 下面定義下面定義 cylinder類的成員函數(shù)類的成員函數(shù)cylinder : cylinder (float a,
20、float b, float r,float h) : circle (a,b,r), height (h) / point的構(gòu)造函數(shù)的構(gòu)造函數(shù)float cylinder : area( ) const / 計(jì)算圓柱表面積計(jì)算圓柱表面積 return 2* circle : area( )+2*3.14159*radius*height; Float cylinder : volume( ) const return circle:area( )*height; / 求圓柱體積求圓柱體積ostream &operator (ostream &output, const cyl
21、inder &cy) / 重載運(yùn)算符重載運(yùn)算符 output“x=“cy.x“, y=“cy.y“, r=” cy.radius “, height=“cy.height“, area=“cy.area( ) “,volume=“cy.volume( )endl; return output;C+ 6- 16 最后寫出主函數(shù)最后寫出主函數(shù)void main( ) cylinder cy1(3.0, 6.0, 2.0, 10.0 ); cout“original cylinder: n“cy1; cy1.setHeight(15.0); cy1.setRadius(7.5); cy1.s
22、etPoint(5, 5); cout“new cylinder: n“cy1; point &pRef = cy1; cout“n pRef as a point:”pRef; circle &cRef =cy1; cout“n cRef as a circle:”cRef;C+ 6- 17 9.3 虛函數(shù)與運(yùn)行時(shí)多態(tài)虛函數(shù)與運(yùn)行時(shí)多態(tài)上節(jié)介紹的程序中,上節(jié)介紹的程序中,circle 類和類和 cylinder 類都定義了類都定義了 area 函數(shù),但功能不一樣。前者是求圓面積,后者是求圓柱函數(shù),但功能不一樣。前者是求圓面積,后者是求圓柱體表面積。由于處在不同的類中,同名是合
23、法的。體表面積。由于處在不同的類中,同名是合法的。如果在圓柱體對象如果在圓柱體對象 cy1中要調(diào)用求圓面積的函數(shù),則應(yīng)中要調(diào)用求圓面積的函數(shù),則應(yīng)該寫成:該寫成:cy1.circle:area( ),而不能寫成,而不能寫成cy1.area( )。用這。用這種方法來區(qū)分兩種同名函數(shù)。使用起來不方便。種方法來區(qū)分兩種同名函數(shù)。使用起來不方便。人們要問,能否用一個(gè)調(diào)用形式,既能調(diào)用派生類的人們要問,能否用一個(gè)調(diào)用形式,既能調(diào)用派生類的函數(shù),又能調(diào)用基類同名函數(shù)?函數(shù),又能調(diào)用基類同名函數(shù)?C+中的中的虛函數(shù)虛函數(shù)就是用來解就是用來解決這一問題。決這一問題。l虛函數(shù)的作用虛函數(shù)的作用:虛函數(shù)的作用是允
24、許在派生類中重新定義與:虛函數(shù)的作用是允許在派生類中重新定義與基類同名的函數(shù),并且可以通過基類指針或引用來訪問基類基類同名的函數(shù),并且可以通過基類指針或引用來訪問基類和派生類中的同名函數(shù)。請看示例程序:和派生類中的同名函數(shù)。請看示例程序:C+ 6- 18 示例示例#include #include using namespace std;class studentpublic: student (int n,string nam, float s) num= n; name= nam; score= s; void display( ) cout“num:”num “name:”name “s
25、core:”scoreendl; protected: int num; string name; float score;class graduate : public studentpublic: graduate (int n, string nam, float s, float p): student (n,nam,s), pay(p) void display( ) cout“num:”num “name:”name “score:”score “pay:”paydisplay( ); / 指向基類對象指向基類對象s1 pt = &g1; pt-display( ); /
26、指向派生類對象指向派生類對象g1,僅僅輸出了派生類的基類數(shù)據(jù)成員,因?yàn)檩敵隽伺缮惖幕悢?shù)據(jù)成員,因?yàn)樗{(diào)用的是基類成員函數(shù)它調(diào)用的是基類成員函數(shù)display! 假如想輸出派生類的全部數(shù)據(jù),當(dāng)然可以采用下面兩種方法之一:假如想輸出派生類的全部數(shù)據(jù),當(dāng)然可以采用下面兩種方法之一:n通過派生類對象名通過派生類對象名g1,調(diào)用派生類對象的成員函數(shù):,調(diào)用派生類對象的成員函數(shù):g1.display( );n定義一個(gè)指向派生類的指針定義一個(gè)指向派生類的指針ptr,并指向,并指向g1,然后用,然后用ptr-display( )。C+ 6- 19 虛函數(shù)虛函數(shù) 我們可以用虛函數(shù)可以順利解決這一問題。方法是
27、:我們可以用虛函數(shù)可以順利解決這一問題。方法是:u在基類在基類student 中聲明中聲明 display函數(shù)時(shí),在最左邊加上一個(gè)關(guān)鍵字函數(shù)時(shí),在最左邊加上一個(gè)關(guān)鍵字virtual :virtual void display( ); 就可以就可以student類的類的display函數(shù)聲明為虛函數(shù),程序其它部分不變編譯運(yùn)函數(shù)聲明為虛函數(shù),程序其它部分不變編譯運(yùn)行后,可見,使用行后,可見,使用pt-display( ),的確將,的確將graduate類對象類對象 g1 的全部數(shù)據(jù)顯示的全部數(shù)據(jù)顯示了出來,說明它調(diào)用的是了出來,說明它調(diào)用的是g1 的成員函數(shù)的成員函數(shù) display。u在派生類中
28、重新定義該函數(shù),要求函數(shù)名、函數(shù)類型、參數(shù)表完全相同。在派生類中重新定義該函數(shù),要求函數(shù)名、函數(shù)類型、參數(shù)表完全相同。u只在類里的成員函數(shù)聲明時(shí),加上關(guān)鍵字只在類里的成員函數(shù)聲明時(shí),加上關(guān)鍵字virtual,在類外定義定義虛函數(shù)時(shí),在類外定義定義虛函數(shù)時(shí),不必加不必加virtual關(guān)鍵字。關(guān)鍵字。u定義一個(gè)指向基類對象的指針,并使她指向同一類族中的某一對象;定義一個(gè)指向基類對象的指針,并使她指向同一類族中的某一對象;u通過該指針變量調(diào)用此虛函數(shù),此時(shí)調(diào)用的就是指針變量指向的對象的同名函通過該指針變量調(diào)用此虛函數(shù),此時(shí)調(diào)用的就是指針變量指向的對象的同名函數(shù)。數(shù)。C+ 6- 20 虛函數(shù)示例虛函數(shù)
29、示例通過使用虛函數(shù)和指針,就能方便地調(diào)用同一類族中不同通過使用虛函數(shù)和指針,就能方便地調(diào)用同一類族中不同類對象的同名函數(shù),只要先用基類指針指向該對象即可。類對象的同名函數(shù),只要先用基類指針指向該對象即可。#include #include using namespace std;class studentpublic: student (int n,string nam, float s) num= n; name= nam; score= s; virtual void display( ) cout“num:”num “name:”name “score:”scoreendl; prote
30、cted: int num; string name; float score;class graduate : public studentpublic: graduate (int n, string nam, float s, float p): student (n,nam,s), pay(p) void display( ) cout“num:”num “name:”name “score:”score “pay:”paydisplay( ); / 指向基類對象指向基類對象s1 pt = &g1; pt-display( ); / 指向派生類對象指向派生類對象g1,調(diào)調(diào)用用g
31、1的顯示函數(shù)的顯示函數(shù)display,輸出,輸出g1全部全部數(shù)據(jù)成員數(shù)據(jù)成員C+ 6- 21 虛函數(shù)示例虛函數(shù)示例例例9-4 用指針用指針+虛函數(shù)的形式實(shí)現(xiàn)動態(tài)聯(lián)編。虛函數(shù)的形式實(shí)現(xiàn)動態(tài)聯(lián)編。class B public: virtual f() ;class P: public B public: f() ;class Q: public B public: f() ;main () B* b_ptr; P p; Q q;b_ptr=&p;b_ptr-f(); /調(diào)用的是調(diào)用的是P:f()b_ptr=&q;b_ptr-f(); /調(diào)用的是調(diào)用的是Q:f()例例9-5 用引用用
32、引用+ 虛函數(shù)的形式實(shí)現(xiàn)動態(tài)聯(lián)虛函數(shù)的形式實(shí)現(xiàn)動態(tài)聯(lián)編。編。class B public: virtual f() ;class P: public B public: f() ;class Q: public B public: f() ;main () P p; Q q;B& b_ref1=p;b_ref.f(); /調(diào)用的是調(diào)用的是P:f()B& b_ref2=q;b_ref2.f(); /調(diào)用的是調(diào)用的是Q:f()C+ 6- 22 將函數(shù)重載與虛函數(shù)比較,可見:將函數(shù)重載與虛函數(shù)比較,可見:u函數(shù)重載是解決的是同一層次上的同名函數(shù)的問題。是橫函數(shù)重載是解決的是同一層次上
33、的同名函數(shù)的問題。是橫向重載。向重載。u虛函數(shù)解決的是不同派生層次上的同名函數(shù)的問題。相當(dāng)虛函數(shù)解決的是不同派生層次上的同名函數(shù)的問題。相當(dāng)于縱向重載。于縱向重載。u同一類族的虛函數(shù)的首部是相同的;而重載函數(shù)的首部不同一類族的虛函數(shù)的首部是相同的;而重載函數(shù)的首部不相同(參數(shù)表不能相同)。相同(參數(shù)表不能相同)。C+ 6- 23 虛函數(shù)何時(shí)為靜態(tài)聯(lián)編虛函數(shù)何時(shí)為靜態(tài)聯(lián)編?何時(shí)為動態(tài)聯(lián)編?何時(shí)為動態(tài)聯(lián)編?l靜態(tài)聯(lián)編與動態(tài)聯(lián)編靜態(tài)聯(lián)編與動態(tài)聯(lián)編C+在編譯或運(yùn)行時(shí),對多個(gè)同名函數(shù)究竟調(diào)用哪一個(gè)函在編譯或運(yùn)行時(shí),對多個(gè)同名函數(shù)究竟調(diào)用哪一個(gè)函數(shù),需要一定的機(jī)制來確定。這種確定調(diào)用的具體對象的過程稱數(shù),
34、需要一定的機(jī)制來確定。這種確定調(diào)用的具體對象的過程稱為為“聯(lián)編聯(lián)編( binding,也稱關(guān)聯(lián),也稱關(guān)聯(lián) )”,即把函數(shù)名與某一個(gè)類對象,即把函數(shù)名與某一個(gè)類對象捆綁在一起。捆綁在一起。函數(shù)重載函數(shù)重載,在編譯時(shí)就可確定其調(diào)用的函數(shù)是哪一個(gè);,在編譯時(shí)就可確定其調(diào)用的函數(shù)是哪一個(gè);通通過對象名調(diào)用虛函數(shù)過對象名調(diào)用虛函數(shù),在編譯時(shí)也可確定其調(diào)用的虛函數(shù)屬于哪,在編譯時(shí)也可確定其調(diào)用的虛函數(shù)屬于哪一個(gè)類。其過程稱為一個(gè)類。其過程稱為“靜態(tài)關(guān)聯(lián)靜態(tài)關(guān)聯(lián)( static binding ),因?yàn)槭窃谶\(yùn),因?yàn)槭窃谶\(yùn)行前進(jìn)行關(guān)聯(lián)的,又成為行前進(jìn)行關(guān)聯(lián)的,又成為早期關(guān)聯(lián)早期關(guān)聯(lián)( early bindin
35、g )。C+ 6- 24 通過通過指針和虛函數(shù)的結(jié)合指針和虛函數(shù)的結(jié)合,在編譯階段是沒法進(jìn)行關(guān)聯(lián)的,在編譯階段是沒法進(jìn)行關(guān)聯(lián)的,因?yàn)榫幾g只作靜態(tài)的語法檢查,光從語句形式因?yàn)榫幾g只作靜態(tài)的語法檢查,光從語句形式pt-display( )無法無法確定調(diào)用的對象,也就沒法關(guān)聯(lián)。確定調(diào)用的對象,也就沒法關(guān)聯(lián)。出現(xiàn)這種情況,我們可以在運(yùn)行階段來處理關(guān)聯(lián)。在運(yùn)行階出現(xiàn)這種情況,我們可以在運(yùn)行階段來處理關(guān)聯(lián)。在運(yùn)行階段,基類指針先指向某一個(gè)對象,然后通過指針調(diào)用該對象的成段,基類指針先指向某一個(gè)對象,然后通過指針調(diào)用該對象的成員函數(shù)。此時(shí)調(diào)用哪個(gè)函數(shù)是確定的,沒有不確定因素。例如員函數(shù)。此時(shí)調(diào)用哪個(gè)函數(shù)是確
36、定的,沒有不確定因素。例如: pt = &g1; pt-display( ); 這種情況由于是在運(yùn)行階段將虛函數(shù)與某一類對象這種情況由于是在運(yùn)行階段將虛函數(shù)與某一類對象“綁定綁定”在一起的,因此稱為在一起的,因此稱為“動態(tài)關(guān)聯(lián)動態(tài)關(guān)聯(lián)( dynamic binding ),或,或“滯后滯后關(guān)聯(lián)關(guān)聯(lián)( late binding )”。C+ 6- 25 l使用虛函數(shù),要注意使用虛函數(shù),要注意u只能用只能用virtual 聲明類的成員函數(shù),類外的普通函數(shù)不能聲明聲明類的成員函數(shù),類外的普通函數(shù)不能聲明成虛函數(shù),因?yàn)樗鼪]有繼承的操作。成虛函數(shù),因?yàn)樗鼪]有繼承的操作。u一個(gè)成員函數(shù)被聲明成虛函數(shù)
37、后,在同一類族中的類就不能一個(gè)成員函數(shù)被聲明成虛函數(shù)后,在同一類族中的類就不能再定義一個(gè)非再定義一個(gè)非virtual的、但與該函數(shù)具有相同參數(shù)表和返回的、但與該函數(shù)具有相同參數(shù)表和返回類型的同名函數(shù)。類型的同名函數(shù)。u使用虛函數(shù),系統(tǒng)要有一定的空間開銷。當(dāng)一個(gè)類帶有虛函使用虛函數(shù),系統(tǒng)要有一定的空間開銷。當(dāng)一個(gè)類帶有虛函數(shù)時(shí),編譯系統(tǒng)會為該類構(gòu)造一個(gè)虛函數(shù)表數(shù)時(shí),編譯系統(tǒng)會為該類構(gòu)造一個(gè)虛函數(shù)表( virtual function table, vtable ),它是一個(gè)指針數(shù)組,存放每個(gè)虛函數(shù)的入口,它是一個(gè)指針數(shù)組,存放每個(gè)虛函數(shù)的入口地址。地址。C+ 6- 26 l什么情況下使用虛函數(shù)?
38、什么情況下使用虛函數(shù)?u成員函數(shù)所在的類是否會作為基類?成員函數(shù)被繼承后有成員函數(shù)所在的類是否會作為基類?成員函數(shù)被繼承后有沒有可能發(fā)生功能變化,如果兩個(gè)因素都具備,就應(yīng)該將沒有可能發(fā)生功能變化,如果兩個(gè)因素都具備,就應(yīng)該將它聲明成虛函數(shù)。它聲明成虛函數(shù)。u如果成員函數(shù)被繼承后功能不變,或派生類用不到該函數(shù),如果成員函數(shù)被繼承后功能不變,或派生類用不到該函數(shù),就不要聲明成虛函數(shù)。就不要聲明成虛函數(shù)。u應(yīng)考慮對成員函數(shù)的訪問是通過對象名還是基類指針,如應(yīng)考慮對成員函數(shù)的訪問是通過對象名還是基類指針,如果是通過果是通過基類指針基類指針或或引用引用訪問,則應(yīng)當(dāng)聲明為虛函數(shù)。訪問,則應(yīng)當(dāng)聲明為虛函數(shù)。
39、u有時(shí)基類中定義虛函數(shù)時(shí)并不定義它的函數(shù)體,即函數(shù)體有時(shí)基類中定義虛函數(shù)時(shí)并不定義它的函數(shù)體,即函數(shù)體為空。其作用只是定義了一個(gè)虛函數(shù)名,具體功能留給派為空。其作用只是定義了一個(gè)虛函數(shù)名,具體功能留給派生類添加(生類添加(純虛函數(shù)純虛函數(shù))。)。C+ 6- 27 l虛析構(gòu)函數(shù)虛析構(gòu)函數(shù)u問題的引出:我們知道,當(dāng)派生類對象撤消時(shí),系統(tǒng)先調(diào)用派生類析問題的引出:我們知道,當(dāng)派生類對象撤消時(shí),系統(tǒng)先調(diào)用派生類析構(gòu)函數(shù),再調(diào)用基類析構(gòu)函數(shù)。但是,如果用構(gòu)函數(shù),再調(diào)用基類析構(gòu)函數(shù)。但是,如果用new 運(yùn)算符建立了一運(yùn)算符建立了一個(gè)派生類臨時(shí)對象,但用一個(gè)基類指針指向它,當(dāng)程序用帶指針參數(shù)個(gè)派生類臨時(shí)對象
40、,但用一個(gè)基類指針指向它,當(dāng)程序用帶指針參數(shù)的的delete 撤消對象時(shí),會發(fā)生讓人不能接受的情況:系統(tǒng)只析構(gòu)基類撤消對象時(shí),會發(fā)生讓人不能接受的情況:系統(tǒng)只析構(gòu)基類對象,而不析構(gòu)派生類對象(即只會調(diào)用基類的析構(gòu)函數(shù),而不會調(diào)對象,而不析構(gòu)派生類對象(即只會調(diào)用基類的析構(gòu)函數(shù),而不會調(diào)用派生類的析構(gòu)函數(shù),這就使得派生類無法執(zhí)行某些清理工作):用派生類的析構(gòu)函數(shù),這就使得派生類無法執(zhí)行某些清理工作):class pointpublic: point( ) point( ) cout“析構(gòu)基類對象析構(gòu)基類對象”endl; ;class circle : public pointpublic: ci
41、rcle( ) circle ( ) cout“析構(gòu)派生類對象析構(gòu)派生類對象”endl; private: int radius;int main( ) point *p = new circle; / 指針為指向基類對象指針,指針為指向基類對象指針, / 但實(shí)際指向臨時(shí)派生類對象但實(shí)際指向臨時(shí)派生類對象 delete p; return 0;C+ 6- 28 解決的辦法:解決的辦法:可以將基類的析構(gòu)函數(shù)聲明為虛析構(gòu)函數(shù)。如:可以將基類的析構(gòu)函數(shù)聲明為虛析構(gòu)函數(shù)。如: virtual point( ) cout“析構(gòu)基類對象析構(gòu)基類對象”endl; 程序其它部分不動,就行了。程序其它部分不動,
42、就行了。當(dāng)基類的析構(gòu)函數(shù)被定義成當(dāng)基類的析構(gòu)函數(shù)被定義成virtual,無論指針指向同,無論指針指向同一類族中的哪一個(gè)對象,當(dāng)撤消對象時(shí),系統(tǒng)會采用動態(tài)關(guān)一類族中的哪一個(gè)對象,當(dāng)撤消對象時(shí),系統(tǒng)會采用動態(tài)關(guān)聯(lián),調(diào)用相應(yīng)的析構(gòu)函數(shù),清理該對象,然后再析構(gòu)基類對聯(lián),調(diào)用相應(yīng)的析構(gòu)函數(shù),清理該對象,然后再析構(gòu)基類對象。象。C+ 6- 29 其他需要注意的問題:其他需要注意的問題:要實(shí)現(xiàn)運(yùn)行時(shí)的多態(tài),需要以下條件:l(1)必須通過指向基類對象的指針,訪問和基類成員函數(shù)同名的派生類成員函數(shù)。或者用派生類對象初始化的基類對象的引用,訪問和基類成員函數(shù)同名的派生類成員函數(shù)。l(2)派生類的繼承方式必須是公有
43、繼承。l(3)基類中的同名成員函數(shù)必須定義為虛函數(shù)。C+ 6- 30 其他需要注意的問題:其他需要注意的問題:使用虛函數(shù)時(shí)要遵循以下規(guī)則:l(1)必須首先在基類中聲明虛函數(shù)。在多級繼承的情況下,也可以不在最高層的基類中聲明虛函數(shù)。例如在第二層定義的虛函數(shù),可以和第三層的虛函數(shù)形成動態(tài)聯(lián)編。但是,一般都是在最高層的基類中首先聲明虛函數(shù)。l(2)基類和派生類的同名函數(shù),函數(shù)名、返回值、參數(shù)表必須全部相同,才能作為虛函數(shù)來使用。否則,即使函數(shù)用virtual 來說明,也不具有虛函數(shù)的行為。l(3)靜態(tài)成員函數(shù)不可以聲明為虛函數(shù)。構(gòu)造函數(shù)也不可以聲明為虛函數(shù)。l(4)析構(gòu)函數(shù)可以聲明為虛函數(shù),即可以定
44、義虛析構(gòu)函數(shù)。l(5)如果在多層繼承中,最高層和第三層有兩個(gè)原型相同的函數(shù),并在最高層中聲明為虛函數(shù),則第三層的這個(gè)函數(shù)也是虛函數(shù)。這種關(guān)系不會因?yàn)榈诙記]有定義這個(gè)函數(shù)而受到影響。例9-7。C+ 6- 31 9.4 純虛函數(shù)與抽象類純虛函數(shù)與抽象類前面已經(jīng)提到,有時(shí)在基類中將某一成員函數(shù)定為虛函前面已經(jīng)提到,有時(shí)在基類中將某一成員函數(shù)定為虛函數(shù)并不是基類本身的需要,而是派生類的需要。在基類中預(yù)留數(shù)并不是基類本身的需要,而是派生類的需要。在基類中預(yù)留一個(gè)函數(shù)名,具體功能留給派生類根據(jù)需要去定義。一個(gè)函數(shù)名,具體功能留給派生類根據(jù)需要去定義。在上一節(jié)中基類在上一節(jié)中基類point 中沒有定義面積
45、中沒有定義面積area函數(shù),是因函數(shù),是因?yàn)闉椤包c(diǎn)點(diǎn)”沒有面積的概念。但是,其直接派生類沒有面積的概念。但是,其直接派生類circle和間接和間接派生類派生類cylinder卻都需要卻都需要area 函數(shù),而且這兩個(gè)函數(shù),而且這兩個(gè)area 函數(shù)的函數(shù)的功能還不相同,一個(gè)是求圓面積,一個(gè)是求圓柱體表面積。功能還不相同,一個(gè)是求圓面積,一個(gè)是求圓柱體表面積。也許會想到,在基類也許會想到,在基類point 中加一個(gè)中加一個(gè)area 函數(shù),并聲明函數(shù),并聲明為虛函數(shù):為虛函數(shù):virtual float area ( ) const return 0; 其返回值為其返回值為0表示表示“點(diǎn)點(diǎn)”沒有面積
46、。其實(shí),在基類中并不沒有面積。其實(shí),在基類中并不使用這個(gè)函數(shù),其返回值也沒有意義。使用這個(gè)函數(shù),其返回值也沒有意義。C+ 6- 32 9.4 純虛函數(shù)與抽象類純虛函數(shù)與抽象類為簡化起見,可以不寫出這種無意義的函數(shù)體,只給出為簡化起見,可以不寫出這種無意義的函數(shù)體,只給出函數(shù)的原型,并在后面加上函數(shù)的原型,并在后面加上“=0”,如:,如:virtual float area( ) const =0 ; / 純虛函數(shù)純虛函數(shù)這就將這就將area聲明為一個(gè)純虛函數(shù)聲明為一個(gè)純虛函數(shù)(pure virtual function)l純虛函數(shù)的聲明形式純虛函數(shù)的聲明形式virtual 函數(shù)類型函數(shù)類型 函
47、數(shù)名函數(shù)名( 參數(shù)表參數(shù)表 ) =0;說明說明u純虛函數(shù)沒有函數(shù)體;純虛函數(shù)沒有函數(shù)體;u最后的最后的“=0”不表示函數(shù)值返回不表示函數(shù)值返回0,它只是形式上的作用,它只是形式上的作用,告訴編譯系統(tǒng):這是純虛函數(shù),告訴編譯系統(tǒng):這是純虛函數(shù),u這是一個(gè)聲明語句,以分號結(jié)尾。這是一個(gè)聲明語句,以分號結(jié)尾。u如果基類中聲明了純虛函數(shù),但派生類中沒有定義該函數(shù),如果基類中聲明了純虛函數(shù),但派生類中沒有定義該函數(shù),則該函數(shù)在派生類中仍為純虛函數(shù)。則該函數(shù)在派生類中仍為純虛函數(shù)。C+ 6- 33 9.4 純虛函數(shù)與抽象類純虛函數(shù)與抽象類l抽象類抽象類u什么叫抽象類?什么叫抽象類?一般聲明了一個(gè)類,用來定
48、義若干對象。一般聲明了一個(gè)類,用來定義若干對象。但有些類并不是用來生成對象,而是作為基類去建立派生但有些類并不是用來生成對象,而是作為基類去建立派生類。類。這種不用來定義對象,而只作為一種基本類型用做繼這種不用來定義對象,而只作為一種基本類型用做繼承的類,就叫抽象類承的類,就叫抽象類( abstract class )。由于抽象類常作。由于抽象類常作為基類,我們也稱為抽象基類為基類,我們也稱為抽象基類( abstract base class )。比如,凡是包含純虛函數(shù)的類都叫抽象類。因?yàn)榧兲摫热?,凡是包含純虛函?shù)的類都叫抽象類。因?yàn)榧兲摵瘮?shù)不能被調(diào)用,包含純虛函數(shù)的類無法建立對象。函數(shù)不能被
49、調(diào)用,包含純虛函數(shù)的類無法建立對象。u抽象類的作用抽象類的作用:是作為一個(gè)類族的共同基類。即,為一個(gè):是作為一個(gè)類族的共同基類。即,為一個(gè)類族提供一個(gè)公共接口。類族提供一個(gè)公共接口。一個(gè)類層次結(jié)構(gòu)中可以不包含任何抽象類,每一層次一個(gè)類層次結(jié)構(gòu)中可以不包含任何抽象類,每一層次的類都可以建立對象。但是,許多系統(tǒng)的頂層是一個(gè)抽象的類都可以建立對象。但是,許多系統(tǒng)的頂層是一個(gè)抽象類,甚至頂部有好幾層都是抽象類。類,甚至頂部有好幾層都是抽象類。C+ 6- 34 9.4 純虛函數(shù)與抽象類純虛函數(shù)與抽象類如果由抽象類所派生出的新類中對基類的所有純虛函數(shù)如果由抽象類所派生出的新類中對基類的所有純虛函數(shù)都進(jìn)行了
50、定義,這個(gè)派生類就不是抽象類,可以被調(diào)用,這個(gè)都進(jìn)行了定義,這個(gè)派生類就不是抽象類,可以被調(diào)用,這個(gè)派生類就成為可以用來定義對象的派生類就成為可以用來定義對象的具體類具體類( concrete class )。如果由抽象類所派生出的新類中對基類的純虛函數(shù)沒有如果由抽象類所派生出的新類中對基類的純虛函數(shù)沒有都進(jìn)行定義,這個(gè)派生類就仍然是抽象類。都進(jìn)行定義,這個(gè)派生類就仍然是抽象類。雖然抽象類不能定義對象,但可以定義指向抽象類的數(shù)雖然抽象類不能定義對象,但可以定義指向抽象類的數(shù)據(jù)的指針。當(dāng)派生類成為具體類之后,就可以用這種指針指向據(jù)的指針。當(dāng)派生類成為具體類之后,就可以用這種指針指向派生類對象,然
51、后通過該指針調(diào)用虛函數(shù),實(shí)現(xiàn)多態(tài)性操作。派生類對象,然后通過該指針調(diào)用虛函數(shù),實(shí)現(xiàn)多態(tài)性操作。下面請看一個(gè)示例,對之前介紹過的以下面請看一個(gè)示例,對之前介紹過的以point為基類的點(diǎn)為基類的點(diǎn)-圓圓-圓柱體類的層次結(jié)構(gòu)進(jìn)行改寫,類的頂層是抽象基類圓柱體類的層次結(jié)構(gòu)進(jìn)行改寫,類的頂層是抽象基類 shape,點(diǎn)、圓、圓柱體都是,點(diǎn)、圓、圓柱體都是shape的直接或間接派生類。的直接或間接派生類。C+ 6- 35 #include class shapepublic: virtual float area( ) const return 0.0; / 虛函數(shù)虛函數(shù) virtual float vol
52、ume( ) const return 0.0; / 虛函數(shù)虛函數(shù) virtual void shapeName( ) const =0; / 純虛函數(shù)純虛函數(shù); / 抽象類不能也不必定義對象抽象類不能也不必定義對象class point : public shapepublic: point (float =0, float =0); void setPoint (float, float); float getX( ) return x; float getY( ) return y; virtual void shapeName ( ) const cout“point:”; / 對虛函
53、數(shù)再定義對虛函數(shù)再定義 friend ostream &operator ( ostream &, const point &);protected: float x,y;point : point (float a, float b) x =a, y = b; void point : setPoint (float a, float b) x = a; y = b; ostream &operator ( ostream &output, const point &p)output“p.x“,” p.y“”; return output;C+
54、 6- 36 class circle : public pointpublic: circle (float x=0, float y=0, float r=0); float getRadius( ) const; virtual float area ( ) const; / 因?yàn)榛惔艘驗(yàn)榛惔撕瘮?shù)定義為虛函數(shù),所以在這里,不管有沒函數(shù)定義為虛函數(shù),所以在這里,不管有沒有有virtual, 只要函數(shù)名、參數(shù)表相同,都是只要函數(shù)名、參數(shù)表相同,都是虛函數(shù)虛函數(shù) virtual void shapeName ( ) const cout“circle:”; / 對虛函數(shù)再定義對虛函數(shù)再定義
55、 friend ostream &operator( ostream &, const circle &);protected: float radius;/ 定義定義circle類成員函數(shù)類成員函數(shù)circle : circle (float x, float y, float r) : point (x,y),radius ( r ) float circle : getRadius ( ) const return radius; float circle : area( ) const return 3.14159 * radius * radius; / 重新
56、定義了重新定義了area 函數(shù)函數(shù)ostream &operator ( ostream &output, const circle &c)output“c.x“,” c.y“, r=”c.radius; return output;/ volume 對于對于point、circle類沒有意義,類沒有意義,只是簡單繼承過來,而沒有重新定義只是簡單繼承過來,而沒有重新定義C+ 6- 37 class cylinder : public circlepublic: cylinder ( float x=0, float y=0, float r=0, float h=0 )
57、; void setHeight (float); virtual float area ( ) const; virtual float volume ( ) const; virtual void shapeName ( ) const cout“cylinder:”; / 對虛函數(shù)再定義對虛函數(shù)再定義 friend ostream &operator( ostream &, const cylinder &);protected: float height;/ 定義定義cylinder類成員函數(shù)類成員函數(shù)cylinder : cylinder ( float a,
58、 float b, float r, float h ) : circle (a,b,r), height (h) void cylinder : setHeight (float h) height= h; float cylinder : area( ) const return 2*circle:area() +2*3.14159 * radius * height;/ 重新定義了重新定義了area 函數(shù)函數(shù)float cylinder : volume ( ) const return circle : area( ) * height; / 重新定義了重新定義了volume 函數(shù)函數(shù)
59、ostream &operator ( ostream &output, const cylinder &cy)output“cy.x“,” cy.y“, r=”cy.radius “,h=“cy.height; return output;C+ 6- 38 void main ( ) point p1(3.2, 4.5); circle c1(2.4, 1.2, 5.6); cylinder cy1(3.5, 6.4, 5.2, 10.5); p1.shapeName( ); / 靜態(tài)關(guān)聯(lián)靜態(tài)關(guān)聯(lián) cout p1 endl; c1.shapeName( ); / 靜態(tài)
60、關(guān)聯(lián)靜態(tài)關(guān)聯(lián) cout c1 endl; cy1.shapeName( ); / 靜態(tài)關(guān)聯(lián)靜態(tài)關(guān)聯(lián) cout cy1 shapeName ( ); / 動態(tài)關(guān)聯(lián)動態(tài)關(guān)聯(lián) cout“x=“p1.getX( ) “,y=“p1.getY( ) “narea=“area( ) “nvolume=“ volume( )shapeName( ); / 動態(tài)關(guān)聯(lián)動態(tài)關(guān)聯(lián)cout“x=“c1.getX( )“,y=“ c1.getY( )“narea=“ area( )“nvolume=“ volume( )shapeName( ); / 動態(tài)關(guān)聯(lián)動態(tài)關(guān)聯(lián)cout“x=“cy1.getX( ) “,y=“cy1.getY( ) “narea=“area( ) “nvolume=“ volume( )shapeName( ), 就是動態(tài)關(guān)聯(lián)。就是動態(tài)關(guān)聯(lián)。C+ 6- 39 C+ 6- 40 多態(tài)性把操作細(xì)節(jié)留給類的設(shè)計(jì)者(專業(yè)人員)去完多態(tài)性把操作細(xì)節(jié)留給類的設(shè)計(jì)者(專業(yè)人員)去完成,而讓編程人員(類的使用者)只需做一些宏觀性的工作,成,而讓編程人員(類的使用者)只需做一些宏觀性的工作,告訴系統(tǒng)做什么,不必考慮怎么做,
溫馨提示
- 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)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 國際關(guān)系學(xué)院《工程力學(xué)與機(jī)械設(shè)計(jì)》2023-2024學(xué)年第二學(xué)期期末試卷
- 河北環(huán)境工程學(xué)院《護(hù)理學(xué)基礎(chǔ)技術(shù)(一)》2023-2024學(xué)年第二學(xué)期期末試卷
- 南京航空航天大學(xué)金城學(xué)院《細(xì)胞生物學(xué)課程設(shè)計(jì)》2023-2024學(xué)年第二學(xué)期期末試卷
- 廣州城市職業(yè)學(xué)院《戰(zhàn)略管理》2023-2024學(xué)年第二學(xué)期期末試卷
- 廣東新安職業(yè)技術(shù)學(xué)院《生物化學(xué)及實(shí)驗(yàn)》2023-2024學(xué)年第二學(xué)期期末試卷
- 長春師范大學(xué)《汽車底盤構(gòu)造與維修》2023-2024學(xué)年第二學(xué)期期末試卷
- 山西華澳商貿(mào)職業(yè)學(xué)院《移動通信技術(shù)》2023-2024學(xué)年第二學(xué)期期末試卷
- 大學(xué)生畢業(yè)實(shí)習(xí)計(jì)劃
- 大一新生軍訓(xùn)心得感悟(28篇)
- 農(nóng)村亂占耕地建房問題整治工作匯報(bào)范文(3篇)
- 小學(xué)體積單位換算練習(xí)100道及答案
- 第7課《誰是最可愛的人》公開課一等獎(jiǎng)創(chuàng)新教學(xué)設(shè)計(jì)-2
- 人音版四年級音樂下冊全冊教學(xué)設(shè)計(jì)教案表格式
- 骨盆骨折小講課護(hù)理課件
- 渣土車司機(jī)安全培訓(xùn)
- 分布式儲能系統(tǒng)的成本效益評估
- 二次函數(shù)(最全的中考二次函數(shù)知識點(diǎn)總結(jié))
- 建筑衛(wèi)生陶瓷生產(chǎn)英文資料
- 網(wǎng)絡(luò)意識形態(tài)安全
- 汽油安全技術(shù)說明書(MSDS)
- 人工智能的倫理問題及其治理研究
評論
0/150
提交評論