第08章多態(tài)性_第1頁(yè)
第08章多態(tài)性_第2頁(yè)
第08章多態(tài)性_第3頁(yè)
第08章多態(tài)性_第4頁(yè)
第08章多態(tài)性_第5頁(yè)
已閱讀5頁(yè),還剩90頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、20009-3-241面向?qū)ο蟪绦蛟O(shè)計(jì)(下)面向?qū)ο蟪绦蛟O(shè)計(jì)(下) 課程講義課程講義 C+2課程大綱3多態(tài)性的概念l 多態(tài)性是面向?qū)ο蟪绦蛟O(shè)計(jì)的重要特征多態(tài)性是面向?qū)ο蟪绦蛟O(shè)計(jì)的重要特征之一。之一。l 多態(tài)性是指發(fā)出同樣的消息被不同類(lèi)型多態(tài)性是指發(fā)出同樣的消息被不同類(lèi)型的對(duì)象接收時(shí)有可能導(dǎo)致完全不同的行的對(duì)象接收時(shí)有可能導(dǎo)致完全不同的行為。為。l 多態(tài)的實(shí)現(xiàn):多態(tài)的實(shí)現(xiàn): 函數(shù)重載函數(shù)重載 運(yùn)算符重載運(yùn)算符重載 虛函數(shù)虛函數(shù)4多態(tài)性的概念5多態(tài)性的例子6問(wèn)題舉例復(fù)數(shù)的運(yùn)算運(yùn)算符重載class Complex class Complex /復(fù)數(shù)類(lèi)聲明復(fù)數(shù)類(lèi)聲明public:public:Comp

2、lex(double r = 0.0,double i = 0.0) Complex(double r = 0.0,double i = 0.0) real = r; imag=i; real = r; imag=i; void display() const;void display() const; /顯示復(fù)數(shù)的值顯示復(fù)數(shù)的值private:private:double real;double real;double imag;double imag;710問(wèn)題舉例復(fù)數(shù)的運(yùn)算l 用用“+”、“-”能夠?qū)崿F(xiàn)復(fù)數(shù)的加減運(yùn)能夠?qū)崿F(xiàn)復(fù)數(shù)的加減運(yùn)算嗎?算嗎?l 實(shí)現(xiàn)復(fù)數(shù)加減運(yùn)算的方法實(shí)現(xiàn)復(fù)數(shù)加減運(yùn)算

3、的方法 重載重載“+”、“-”運(yùn)算符運(yùn)算符運(yùn)算符重載11運(yùn)算符重載的實(shí)質(zhì)運(yùn)算符重載l 運(yùn)算符重載是對(duì)已有的運(yùn)算符賦予多重含義運(yùn)算符重載是對(duì)已有的運(yùn)算符賦予多重含義l 必要性必要性 C+中預(yù)定義的運(yùn)算符其運(yùn)算對(duì)象只能是基本數(shù)中預(yù)定義的運(yùn)算符其運(yùn)算對(duì)象只能是基本數(shù)據(jù)類(lèi)型,而不適用于用戶(hù)自定義類(lèi)型(如類(lèi))據(jù)類(lèi)型,而不適用于用戶(hù)自定義類(lèi)型(如類(lèi))l 實(shí)現(xiàn)機(jī)制實(shí)現(xiàn)機(jī)制 將指定的運(yùn)算表達(dá)式轉(zhuǎn)化為對(duì)運(yùn)算符函數(shù)的調(diào)用,將指定的運(yùn)算表達(dá)式轉(zhuǎn)化為對(duì)運(yùn)算符函數(shù)的調(diào)用,運(yùn)算對(duì)象轉(zhuǎn)化為運(yùn)算符函數(shù)的實(shí)參。運(yùn)算對(duì)象轉(zhuǎn)化為運(yùn)算符函數(shù)的實(shí)參。 編譯系統(tǒng)對(duì)重載運(yùn)算符的選擇,遵循函數(shù)重載的選編譯系統(tǒng)對(duì)重載運(yùn)算符的選擇,遵循函數(shù)重載

4、的選擇原則。擇原則。12兩種形式運(yùn)算符重載l 重載為類(lèi)的非靜態(tài)成員函數(shù)重載為類(lèi)的非靜態(tài)成員函數(shù)l 重載為非成員函數(shù)重載為非成員函數(shù)13運(yùn)算符重載的方法運(yùn)算符重載的方法運(yùn)算符重載14運(yùn)算符函數(shù)運(yùn)算符函數(shù)運(yùn)算符重載l 聲明形式聲明形式函數(shù)類(lèi)型函數(shù)類(lèi)型 operator 運(yùn)算符(形參)運(yùn)算符(形參) .l 重載為類(lèi)成員函數(shù)時(shí)重載為類(lèi)成員函數(shù)時(shí) 參數(shù)個(gè)數(shù)參數(shù)個(gè)數(shù)=原操作數(shù)個(gè)數(shù)原操作數(shù)個(gè)數(shù)-1 (后置(后置+、-除外)除外)l 重載為非成員函數(shù)時(shí)重載為非成員函數(shù)時(shí) 參數(shù)個(gè)數(shù)參數(shù)個(gè)數(shù)=原操作數(shù)個(gè)數(shù)原操作數(shù)個(gè)數(shù),且至少應(yīng)該有一個(gè)自定義類(lèi)型的形參。且至少應(yīng)該有一個(gè)自定義類(lèi)型的形參。15規(guī)則和限制運(yùn)算符重載l

5、C+中能夠被重載的運(yùn)算符有:中能夠被重載的運(yùn)算符有:new delete new delete+ - * / % & | ! = += -= *= /= %= &= |= = = != = & |+ - , -* -() 16規(guī)則和限制運(yùn)算符重載l C+中不能夠被重載的運(yùn)算符有:中不能夠被重載的運(yùn)算符有:17規(guī)則和限制(續(xù))運(yùn)算符重載l 只能重載只能重載C+語(yǔ)言中已有的運(yùn)算符,語(yǔ)言中已有的運(yùn)算符,不可臆造新的。不可臆造新的。l 不改變?cè)\(yùn)算符的優(yōu)先級(jí)和結(jié)合性。不改變?cè)\(yùn)算符的優(yōu)先級(jí)和結(jié)合性。l 不能改變操作數(shù)個(gè)數(shù)。不能改變操作數(shù)個(gè)數(shù)。l 經(jīng)重載的運(yùn)算符,其操作數(shù)中至少應(yīng)

6、該經(jīng)重載的運(yùn)算符,其操作數(shù)中至少應(yīng)該有一個(gè)是自定義類(lèi)型。有一個(gè)是自定義類(lèi)型。18規(guī)則和限制(續(xù))運(yùn)算符重載19運(yùn)算符成員函數(shù)的設(shè)計(jì)運(yùn)算符重載l 雙目運(yùn)算符雙目運(yùn)算符 B 如果要重載如果要重載 B 為類(lèi)成員函數(shù),使之能夠?qū)崿F(xiàn)為類(lèi)成員函數(shù),使之能夠?qū)崿F(xiàn)表達(dá)式表達(dá)式 oprd1 B oprd2,其中,其中 oprd1 為為A 類(lèi)對(duì)象,則類(lèi)對(duì)象,則 B 應(yīng)被重載為應(yīng)被重載為 A 類(lèi)的成員函數(shù),類(lèi)的成員函數(shù),形參類(lèi)型應(yīng)該是形參類(lèi)型應(yīng)該是 oprd2 所屬的類(lèi)型。所屬的類(lèi)型。 經(jīng)重載后,表達(dá)式經(jīng)重載后,表達(dá)式 oprd1 B oprd2 相當(dāng)于相當(dāng)于 oprd1.operator B(oprd2)20例

7、8-1運(yùn)算符重載 將將“+”+”、“-”-”運(yùn)算重載為復(fù)數(shù)類(lèi)的運(yùn)算重載為復(fù)數(shù)類(lèi)的成員函數(shù)。成員函數(shù)。實(shí)部和虛部分別相加減。兩個(gè)操作數(shù)都是復(fù)數(shù)類(lèi)的對(duì)象。21 #include #include using namespace std;using namespace std;class Complex class Complex /復(fù)數(shù)類(lèi)定義復(fù)數(shù)類(lèi)定義public:public:/外部接口外部接口Complex(double r = 0.0, double i = 0.0) : Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) r

8、eal(r), imag(i) /構(gòu)造函數(shù)構(gòu)造函數(shù)Complex operator + (const Complex &c2) const;Complex operator + (const Complex &c2) const;/運(yùn)算符運(yùn)算符+ +重載成員函數(shù)重載成員函數(shù)Complex operator - (const Complex &c2) const;Complex operator - (const Complex &c2) const;/運(yùn)算符運(yùn)算符- -重載成員函數(shù)重載成員函數(shù)void display() const;void display()

9、 const; /輸出復(fù)數(shù)輸出復(fù)數(shù)private:private:/私有數(shù)據(jù)成員私有數(shù)據(jù)成員double real;double real;/復(fù)數(shù)實(shí)部復(fù)數(shù)實(shí)部double imag;double imag;/復(fù)數(shù)虛部復(fù)數(shù)虛部;22 Complex Complex:operator + (const Complex &c2) Complex Complex:operator + (const Complex &c2) const const /重載運(yùn)算符函數(shù)實(shí)現(xiàn)重載運(yùn)算符函數(shù)實(shí)現(xiàn)return return Complex(real + c2.real, imag + c2.ima

10、g);Complex(real + c2.real, imag + c2.imag); /創(chuàng)建一個(gè)臨時(shí)無(wú)名對(duì)象作為返回值創(chuàng)建一個(gè)臨時(shí)無(wú)名對(duì)象作為返回值 Complex Complex:operator - (const Complex &c2) Complex Complex:operator - (const Complex &c2) const const /重載運(yùn)算符函數(shù)實(shí)現(xiàn)重載運(yùn)算符函數(shù)實(shí)現(xiàn)return return Complex(real - c2.real, imag - c2.imag);Complex(real - c2.real, imag - c2.ima

11、g); /創(chuàng)建一個(gè)臨時(shí)無(wú)名對(duì)象作為返回值創(chuàng)建一個(gè)臨時(shí)無(wú)名對(duì)象作為返回值 23 void Complex:display() const void Complex:display() const cout ( real , imag ) endl;cout ( real , imag ) endl; int main() int main() /主函數(shù)主函數(shù)Complex c1(5, 4), c2(2, 10), c3Complex c1(5, 4), c2(2, 10), c3;/;/定義復(fù)數(shù)類(lèi)的對(duì)象定義復(fù)數(shù)類(lèi)的對(duì)象cout c1 = ; c1.display();cout c1 = ; c1

12、.display();cout c2 = ; c2.display();cout c2 = ; c2.display();c3 = c3 = c1 - c2c1 - c2; ;/使用重載運(yùn)算符完成復(fù)數(shù)減法使用重載運(yùn)算符完成復(fù)數(shù)減法cout c3 = c1 - c2 = ; c3.display();cout c3 = c1 - c2 = ; c3.display();c3 = c3 = c1 + c2c1 + c2; ;/使用重載運(yùn)算符完成復(fù)數(shù)加法使用重載運(yùn)算符完成復(fù)數(shù)加法cout c3 = c1 + c2 = ; c3.display();cout c3 = c1 + c2 = ; c3.d

13、isplay();return 0;return 0; 24 程序輸出的結(jié)果為:程序輸出的結(jié)果為:c1 = (5, 4)c2 = (2, 10)c3 = c1 - c2 = (3, -6)c3 = c1 + c2 = (7, 14)25運(yùn)算符成員函數(shù)的設(shè)計(jì)運(yùn)算符重載l 前置單目運(yùn)算符前置單目運(yùn)算符 U 如果要重載 U 為類(lèi)成員函數(shù),使之能夠?qū)崿F(xiàn)表達(dá)式 U oprd,其中 oprd 為A類(lèi)對(duì)象,則 U 應(yīng)被重載為 A 類(lèi)的成員函數(shù),無(wú)形參。 經(jīng)重載后,表達(dá)式 U oprd 相當(dāng)于 oprd.operator U()26運(yùn)算符成員函數(shù)的設(shè)計(jì)運(yùn)算符重載l 后置單目運(yùn)算符后置單目運(yùn)算符 +和和- 如果

14、要重載 +或-為類(lèi)成員函數(shù),使之能夠?qū)崿F(xiàn)表達(dá)式 oprd+ 或或 oprd- ,其中 oprd 為A類(lèi)對(duì)象,則 +或- 應(yīng)被重載為 A 類(lèi)的成員函數(shù),且具有一個(gè) int 類(lèi)型形參。 經(jīng)重載后,表達(dá)式 oprd+ 相當(dāng)于 oprd.operator +(0)27例8-2運(yùn)算符重載l 運(yùn)算符前置運(yùn)算符前置+和后置和后置+重載為時(shí)鐘類(lèi)的成重載為時(shí)鐘類(lèi)的成員函數(shù)。員函數(shù)。l 前置單目運(yùn)算符,重載函數(shù)沒(méi)有形參,對(duì)前置單目運(yùn)算符,重載函數(shù)沒(méi)有形參,對(duì)于后置單目運(yùn)算符,重載函數(shù)需要有一個(gè)于后置單目運(yùn)算符,重載函數(shù)需要有一個(gè)整型形參。整型形參。l 操作數(shù)是時(shí)鐘類(lèi)的對(duì)象。操作數(shù)是時(shí)鐘類(lèi)的對(duì)象。l 實(shí)現(xiàn)時(shí)間增加實(shí)

15、現(xiàn)時(shí)間增加1秒鐘。秒鐘。28 #include #include using namespace std;using namespace std;class Clock class Clock /時(shí)鐘類(lèi)聲明定義時(shí)鐘類(lèi)聲明定義public:public:/外部接口外部接口Clock(int hour=0,int minute=0, int second = 0);Clock(int hour=0,int minute=0, int second = 0);void showTime() const;void showTime() const;Clock& operator + ();Cl

16、ock& operator + (); /前置單目運(yùn)算符重載前置單目運(yùn)算符重載Clock operator + (int);/Clock operator + (int);/后置單目運(yùn)算符重載后置單目運(yùn)算符重載private:private:/私有數(shù)據(jù)成員私有數(shù)據(jù)成員int hour, minute, second;int hour, minute, second;29 /前置單目運(yùn)算符重載函數(shù)前置單目運(yùn)算符重載函數(shù)Clock & Clock:operator + () Clock & Clock:operator + () second+;second+;if (se

17、cond = 60) if (second = 60) second -= 60;second -= 60;minute+;minute+;if (minute = 60) if (minute = 60) minute -= 60;minute -= 60;hour = (hour + 1) % 24;hour = (hour + 1) % 24; return return * *this;this; 30 /后置單目運(yùn)算符重載后置單目運(yùn)算符重載Clock Clock:operator + (int) Clock Clock:operator + (int) /注意形參表中的整型參數(shù)注意形

18、參表中的整型參數(shù)Clock old = Clock old = * *this;this;+(+(* *this);this);/調(diào)用前置調(diào)用前置“+”+”運(yùn)算符運(yùn)算符return old;return old; 31 /其它成員函數(shù)的實(shí)現(xiàn)略其它成員函數(shù)的實(shí)現(xiàn)略int main() int main() Clock myClock(23, 59, 59);Clock myClock(23, 59, 59);cout First time output: ;cout First time output: ;myClock.showTime();myClock.showTime();cout Sh

19、ow myClock+: ;cout Show myClock+: ;( (myClock+myClock+).showTime();).showTime();cout Show +myClock: ;cout Show +myClock: ;(+myClock(+myClock).showTime();).showTime();return 0;return 0; 32 程序運(yùn)行結(jié)果為:程序運(yùn)行結(jié)果為:First time output: 23:59:59First time output: 23:59:59Show myClock+: 23:59:59Show myClock+: 23:5

20、9:59Show +myClock: 0:0:1Show +myClock: 0:0:133運(yùn)算符非成員函數(shù)的設(shè)計(jì)友元函數(shù)運(yùn)算符重載l 如果在運(yùn)算符的重載函數(shù)中需要操作某如果在運(yùn)算符的重載函數(shù)中需要操作某類(lèi)對(duì)象的私有成員,可以將此函數(shù)聲明類(lèi)對(duì)象的私有成員,可以將此函數(shù)聲明為該類(lèi)的友元。為該類(lèi)的友元。l 函數(shù)的形參代表依自左至右次序排列的函數(shù)的形參代表依自左至右次序排列的各操作數(shù)。各操作數(shù)。l 后置單目運(yùn)算符后置單目運(yùn)算符 +和和-的重載函數(shù),的重載函數(shù),形參列表中要增加一個(gè)形參列表中要增加一個(gè)int,但不必寫(xiě),但不必寫(xiě)形參名。形參名。34運(yùn)算符非成員函數(shù)的設(shè)計(jì)運(yùn)算符重載l 雙目運(yùn)算符雙目運(yùn)算符

21、 B重載后,重載后,表達(dá)式oprd1 B oprd2 等同于operator B(oprd1,oprd2 )l 前置單目運(yùn)算符前置單目運(yùn)算符 B重載后,重載后,表達(dá)式 B oprd 等同于operator B(oprd )l 后置單目運(yùn)算符后置單目運(yùn)算符 +和和-重載后,重載后,表達(dá)式 oprd B 等同于operator B(oprd,0 )35例8-3運(yùn)算符重載o 將將+ +、- -(雙目)重載為非成員函數(shù),(雙目)重載為非成員函數(shù),并將其聲明為復(fù)數(shù)并將其聲明為復(fù)數(shù)類(lèi)的友元,兩個(gè)操作數(shù)都是復(fù)數(shù)類(lèi)的常引用。類(lèi)的友元,兩個(gè)操作數(shù)都是復(fù)數(shù)類(lèi)的常引用。o 將將(雙目)重載為非成員函數(shù),并將其聲明為

22、復(fù)數(shù)類(lèi)(雙目)重載為非成員函數(shù),并將其聲明為復(fù)數(shù)類(lèi)的友元,它的左操作數(shù)是的友元,它的左操作數(shù)是std:ostream引用,右操作數(shù)為引用,右操作數(shù)為復(fù)數(shù)類(lèi)的常引用,返回復(fù)數(shù)類(lèi)的常引用,返回std:ostream引用,用以支持下面引用,用以支持下面形式的輸出:形式的輸出:cout cout a a b; b;該輸出調(diào)用的是:該輸出調(diào)用的是:operator operator (operator (operator (cout, a), b); (cout, a), b);36 #include #include using namespace std;using namespace std;cl

23、ass Complex class Complex /復(fù)數(shù)類(lèi)定義復(fù)數(shù)類(lèi)定義public:public:/外部接口外部接口Complex(double r = 0.0, double i = 0.0) : real(r), Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) imag(i) /構(gòu)造函數(shù)構(gòu)造函數(shù)friend Complex operator + (const Complex &c1, const friend Complex operator + (const Complex &c1, const C

24、omplex &c2);Complex &c2);/運(yùn)算符運(yùn)算符+ +重載重載friend Complex operator - (const Complex &c1, const friend Complex operator - (const Complex &c1, const Complex &c2);Complex &c2);/運(yùn)算符運(yùn)算符- -重載重載friend ostream & operator (ostream &out, const friend ostream & operator (ostream

25、 &out, const Complex &c); /Complex &c); /運(yùn)算符運(yùn)算符重載重載private:private:/私有數(shù)據(jù)成員私有數(shù)據(jù)成員double real;double real;/復(fù)數(shù)實(shí)部復(fù)數(shù)實(shí)部double imag;double imag;/復(fù)數(shù)虛部復(fù)數(shù)虛部;37 Complex Complex operator +operator + (const Complex &c1, const Complex &c2) (const Complex &c1, const Complex &c2) return

26、Complex(c1.real + c2.real, c1.imag + c2.imag); return Complex(c1.real + c2.real, c1.imag + c2.imag); Complex Complex operator -operator - (const Complex &c1, const Complex &c2) (const Complex &c1, const Complex &c2) return Complex(c1.real - c2.real, c1.imag - c2.imag); return Complex

27、(c1.real - c2.real, c1.imag - c2.imag); ostream & ostream & operator operator (ostream &out, const Complex &c) (ostream &out, const Complex &c) out ( c.real , c.imag );out ( c.real , c.imag );return out;return out; 38靜態(tài)綁定與動(dòng)態(tài)綁定l 綁定綁定程序自身彼此關(guān)聯(lián)的過(guò)程,確定程序中的程序自身彼此關(guān)聯(lián)的過(guò)程,確定程序中的操作調(diào)用與執(zhí)行該

28、操作的代碼間的關(guān)系。操作調(diào)用與執(zhí)行該操作的代碼間的關(guān)系。l 靜態(tài)綁定靜態(tài)綁定綁定過(guò)程出現(xiàn)在編譯階段,用對(duì)象名或者綁定過(guò)程出現(xiàn)在編譯階段,用對(duì)象名或者類(lèi)名來(lái)限定要調(diào)用的函數(shù)。類(lèi)名來(lái)限定要調(diào)用的函數(shù)。l 動(dòng)態(tài)綁定動(dòng)態(tài)綁定綁定工作在程序運(yùn)行時(shí)執(zhí)行,在程序運(yùn)行綁定工作在程序運(yùn)行時(shí)執(zhí)行,在程序運(yùn)行時(shí)才確定將要調(diào)用的函數(shù)。時(shí)才確定將要調(diào)用的函數(shù)。39 #include#includeusing namespace std;using namespace std;class class PointPoint public:public:Point(double x, double y) : x(x), y(

29、y) Point(double x, double y) : x(x), y(y) doubledouble areaarea() const return 0.0; () const return 0.0; private:private:double x, y;double x, y;class class RectangleRectangle: public : public PointPoint public:public:Rectangle(double x, double y, double w, double h);Rectangle(double x, double y, do

30、uble w, double h);double double areaarea() const return w () const return w * * h; h; private:private:double w, h;double w, h;40 Rectangle:Rectangle(double x, double y, double w, Rectangle:Rectangle(double x, double y, double w, double h) :double h) :PointPoint(x, y), w(w), h(h) (x, y), w(w), h(h) v

31、oid fun(const void fun(const Point &sPoint &s) ) cout Area = s.area() endl;cout Area = s.area() endl; int main() int main() Rectangle recRectangle rec(3.0, 5.2, 15.0, 25.0);(3.0, 5.2, 15.0, 25.0);fun(fun(recrec););return 0;return 0; 運(yùn)行結(jié)果:運(yùn)行結(jié)果:Area = 0Area = 041 #include#includeusing namespac

32、e std;using namespace std;class Point class Point public:public:Point(double x, double y) : x(x), y(y) Point(double x, double y) : x(x), y(y) virtualvirtual double area() const return 0.0; double area() const return 0.0; private:private:double x, y;double x, y;class Rectangle:public Point class Rect

33、angle:public Point public:public:Rectangle(double x, double y, double w, double h);Rectangle(double x, double y, double w, double h);virtualvirtual double area() const return w double area() const return w * * h; h; private: private:double w, h;double w, h;/其他函數(shù)同上例其他函數(shù)同上例42 void fun(const void fun(c

34、onst Point &sPoint &s) ) cout Area = cout Area = s s.area() endl;.area() endl; int main() int main() Rectangle recRectangle rec(3.0, 5.2, 15.0, 25.0);(3.0, 5.2, 15.0, 25.0);fun(fun(recrec););return 0;return 0; 運(yùn)行結(jié)果:運(yùn)行結(jié)果:Area = 375Area = 37543虛函數(shù)的作用虛函數(shù)44虛函數(shù)虛函數(shù)l 虛函數(shù)是動(dòng)態(tài)綁定的基礎(chǔ)。虛函數(shù)是動(dòng)態(tài)綁定的基礎(chǔ)。l 是非靜態(tài)的

35、成員函數(shù)。是非靜態(tài)的成員函數(shù)。l 在類(lèi)的聲明中,在函數(shù)原型之前寫(xiě)在類(lèi)的聲明中,在函數(shù)原型之前寫(xiě)virtual。l virtual 只用來(lái)說(shuō)明類(lèi)聲明中的原型,不能用在只用來(lái)說(shuō)明類(lèi)聲明中的原型,不能用在函數(shù)實(shí)現(xiàn)時(shí)。函數(shù)實(shí)現(xiàn)時(shí)。l 具有繼承性,基類(lèi)中聲明了虛函數(shù),派生類(lèi)中無(wú)具有繼承性,基類(lèi)中聲明了虛函數(shù),派生類(lèi)中無(wú)論是否說(shuō)明,同原型函數(shù)都自動(dòng)為虛函數(shù)。論是否說(shuō)明,同原型函數(shù)都自動(dòng)為虛函數(shù)。l 本質(zhì):不是重載聲明而是覆蓋。本質(zhì):不是重載聲明而是覆蓋。l 調(diào)用方式:通過(guò)基類(lèi)指針或引用,執(zhí)行時(shí)會(huì)調(diào)用方式:通過(guò)基類(lèi)指針或引用,執(zhí)行時(shí)會(huì)根據(jù)根據(jù)指針指向的對(duì)象的類(lèi)指針指向的對(duì)象的類(lèi),決定調(diào)用哪個(gè)函數(shù)。,決定調(diào)用

36、哪個(gè)函數(shù)。54虛函數(shù)的使用55虛函數(shù)的使用56虛函數(shù)的使用57例 8-4虛函數(shù)#include #include using namespace std;using namespace std;class Base1 /class Base1 /基類(lèi)基類(lèi)Base1Base1定義定義public:public:virtualvirtual void void displaydisplay() const;() const; /虛函數(shù)虛函數(shù);void Base1:display() const void Base1:display() const cout Base1:display() endl

37、;cout Base1:display() endl; class Base2: public Base1 /class Base2: public Base1 /公有派生類(lèi)公有派生類(lèi)Base2Base2定義定義public:public:void void displaydisplay() const;() const;/覆蓋基類(lèi)的虛函數(shù)覆蓋基類(lèi)的虛函數(shù);void Base2:display() const void Base2:display() const cout Base2:display() endl;cout Base2:display() endl; 58 /公有派生類(lèi)公有派生

38、類(lèi)DerivedDerived定義定義class Derived: public Base2 class Derived: public Base2 public:public:void void displaydisplay() const; /() const; /覆蓋基類(lèi)的虛函數(shù)覆蓋基類(lèi)的虛函數(shù);void Derived:display() const void Derived:display() const cout Derived:display() endl;cout Derived:display() display();ptr-display();/對(duì)象指針對(duì)象指針-成員名成員

39、名 59 int main() int main() /主函數(shù)主函數(shù)Base1 base1;Base1 base1;/定義定義Base1Base1類(lèi)對(duì)象類(lèi)對(duì)象Base2 base2;Base2 base2;/定義定義Base2Base2類(lèi)對(duì)象類(lèi)對(duì)象Derived derived;Derived derived;/定義定義DerivedDerived類(lèi)對(duì)象類(lèi)對(duì)象fun(&base1);fun(&base1);/用用Base1Base1對(duì)象的指針調(diào)用對(duì)象的指針調(diào)用funfun函數(shù)函數(shù)fun(&base2);fun(&base2);/用用Base2Base2對(duì)象的指針

40、調(diào)用對(duì)象的指針調(diào)用funfun函數(shù)函數(shù)fun(&derived);fun(&derived); /用用DerivedDerived對(duì)象的指針調(diào)用對(duì)象的指針調(diào)用funfun函數(shù)函數(shù)return 0;return 0; 運(yùn)行結(jié)果:運(yùn)行結(jié)果:Base1:display()Base2:display()Derived:display()60虛析構(gòu)函數(shù)虛函數(shù)為什么需要虛析構(gòu)函數(shù)?為什么需要虛析構(gòu)函數(shù)?l 可能通過(guò)基類(lèi)指針刪除派生類(lèi)對(duì)象;可能通過(guò)基類(lèi)指針刪除派生類(lèi)對(duì)象;l 如果你打算允許其他人通過(guò)基類(lèi)指針調(diào)如果你打算允許其他人通過(guò)基類(lèi)指針調(diào)用對(duì)象的析構(gòu)函數(shù)(通過(guò)用對(duì)象的析構(gòu)函數(shù)(通過(guò)del

41、ete這樣這樣做是正常的),就需要讓基類(lèi)的析構(gòu)函做是正常的),就需要讓基類(lèi)的析構(gòu)函數(shù)成為虛函數(shù),否則執(zhí)行數(shù)成為虛函數(shù),否則執(zhí)行delete的結(jié)的結(jié)果是不確定的。果是不確定的。61虛析構(gòu)函數(shù)虛函數(shù)69抽象類(lèi)虛函數(shù)與抽象類(lèi)帶有純虛函數(shù)的類(lèi)稱(chēng)為抽象類(lèi)帶有純虛函數(shù)的類(lèi)稱(chēng)為抽象類(lèi):class 類(lèi)名類(lèi)名 virtual 類(lèi)型 函數(shù)名(參數(shù)表)=0; /純虛函數(shù) .70抽象類(lèi)虛函數(shù)與抽象類(lèi)71抽象類(lèi)虛函數(shù)與抽象類(lèi)l 作用作用 抽象類(lèi)為抽象和設(shè)計(jì)的目的而聲明,將有關(guān)的數(shù)據(jù)抽象類(lèi)為抽象和設(shè)計(jì)的目的而聲明,將有關(guān)的數(shù)據(jù)和行為組織在一個(gè)繼承層次結(jié)構(gòu)中,保證派生類(lèi)具和行為組織在一個(gè)繼承層次結(jié)構(gòu)中,保證派生類(lèi)具有要求的

42、行為。有要求的行為。 對(duì)于暫時(shí)無(wú)法實(shí)現(xiàn)的函數(shù),可以聲明為純虛函數(shù),對(duì)于暫時(shí)無(wú)法實(shí)現(xiàn)的函數(shù),可以聲明為純虛函數(shù),留給派生類(lèi)去實(shí)現(xiàn)。留給派生類(lèi)去實(shí)現(xiàn)。l 注意注意 抽象類(lèi)只能作為基類(lèi)來(lái)使用。抽象類(lèi)只能作為基類(lèi)來(lái)使用。 不能聲明抽象類(lèi)的對(duì)象。不能聲明抽象類(lèi)的對(duì)象。 構(gòu)造函數(shù)不能是虛函數(shù),析構(gòu)函數(shù)可以是虛函數(shù)。構(gòu)造函數(shù)不能是虛函數(shù),析構(gòu)函數(shù)可以是虛函數(shù)。72抽象類(lèi)虛函數(shù)與抽象類(lèi)73例 8-5虛函數(shù)與抽象類(lèi)#include #include using namespace std;using namespace std;class Base1 /class Base1 /基類(lèi)基類(lèi)Base1Base1定義

43、定義public:public:virtual void display() const = 0;virtual void display() const = 0; /純虛函數(shù)純虛函數(shù);class Base2: public Base1 /class Base2: public Base1 /公有派生類(lèi)公有派生類(lèi)Base2Base2定義定義public:public:void void displaydisplay() const /() const /覆蓋基類(lèi)的虛函數(shù)覆蓋基類(lèi)的虛函數(shù)cout Base2:display() endl;cout Base2:display() endl; ;c

44、lass Derived: public Base2 /class Derived: public Base2 /公有派生類(lèi)公有派生類(lèi)DerivedDerived定義定義public:public:void void displaydisplay() const /() const /覆蓋基類(lèi)的虛函數(shù)覆蓋基類(lèi)的虛函數(shù)cout Derived:display() endl;cout Derived:display() display();ptr-display();/對(duì)象指針對(duì)象指針-成員名成員名 int main() int main() /主函數(shù)主函數(shù)Base2 base2;Base2 ba

45、se2;/定義定義Base2Base2類(lèi)對(duì)象類(lèi)對(duì)象Derived derived;Derived derived;/定義定義DerivedDerived類(lèi)對(duì)象類(lèi)對(duì)象fun(&base2);fun(&base2);/用用Base2Base2對(duì)象的指針調(diào)用對(duì)象的指針調(diào)用funfun函數(shù)函數(shù)fun(&derived);fun(&derived); /用用DerivedDerived對(duì)象的指針調(diào)用對(duì)象的指針調(diào)用funfun函數(shù)函數(shù)return 0;return 0; 8.6程序?qū)嵗?.6程序?qū)嵗?7深度探索l 多態(tài)類(lèi)型與非多態(tài)類(lèi)型多態(tài)類(lèi)型與非多態(tài)類(lèi)型l 運(yùn)行時(shí)類(lèi)型識(shí)別運(yùn)

46、行時(shí)類(lèi)型識(shí)別l 虛函數(shù)動(dòng)態(tài)綁定的實(shí)現(xiàn)原理虛函數(shù)動(dòng)態(tài)綁定的實(shí)現(xiàn)原理78深度探索深度探索l多態(tài)類(lèi)型與非多態(tài)類(lèi)型多態(tài)類(lèi)型與非多態(tài)類(lèi)型有虛函數(shù)的類(lèi)類(lèi)型稱(chēng)為多態(tài)類(lèi)型有虛函數(shù)的類(lèi)類(lèi)型稱(chēng)為多態(tài)類(lèi)型其它類(lèi)型皆為非多態(tài)類(lèi)型其它類(lèi)型皆為非多態(tài)類(lèi)型l二者的差異二者的差異語(yǔ)言層面的差異語(yǔ)言層面的差異多態(tài)類(lèi)型對(duì)象占用額外的空間多態(tài)類(lèi)型對(duì)象占用額外的空間多態(tài)類(lèi)型支持運(yùn)行時(shí)類(lèi)型識(shí)別多態(tài)類(lèi)型支持運(yùn)行時(shí)類(lèi)型識(shí)別設(shè)計(jì)原則上的差異設(shè)計(jì)原則上的差異79設(shè)計(jì)原則深度探索l 多態(tài)類(lèi)型多態(tài)類(lèi)型多態(tài)類(lèi)型的析構(gòu)函數(shù)一般應(yīng)為虛函數(shù)多態(tài)類(lèi)型的析構(gòu)函數(shù)一般應(yīng)為虛函數(shù)l 非多態(tài)類(lèi)型非多態(tài)類(lèi)型非多態(tài)類(lèi)型不宜作為公共基類(lèi)非多態(tài)類(lèi)型不宜作為公共基類(lèi)由于沒(méi)有

47、利用動(dòng)態(tài)多態(tài)性,一般可以用組合,由于沒(méi)有利用動(dòng)態(tài)多態(tài)性,一般可以用組合,而無(wú)需用共有繼承;而無(wú)需用共有繼承;如果繼承,則由于析構(gòu)函數(shù)不是虛函數(shù),刪除如果繼承,則由于析構(gòu)函數(shù)不是虛函數(shù),刪除對(duì)象時(shí)所執(zhí)行操作與指針類(lèi)型有關(guān),易引起混對(duì)象時(shí)所執(zhí)行操作與指針類(lèi)型有關(guān),易引起混亂。亂。把不需被繼承的類(lèi)型設(shè)定為非多態(tài)類(lèi)型把不需被繼承的類(lèi)型設(shè)定為非多態(tài)類(lèi)型由于成員函數(shù)都是靜態(tài)綁定,調(diào)用速度較快;由于成員函數(shù)都是靜態(tài)綁定,調(diào)用速度較快;對(duì)象占用空間較小。對(duì)象占用空間較小。80運(yùn)行時(shí)類(lèi)型識(shí)別深度探索l 運(yùn)行時(shí)類(lèi)型識(shí)別運(yùn)行時(shí)類(lèi)型識(shí)別 允許在運(yùn)行時(shí)通過(guò)基類(lèi)指針(或引用)辨別對(duì)允許在運(yùn)行時(shí)通過(guò)基類(lèi)指針(或引用)辨別對(duì)

48、象所屬的具體派生類(lèi);象所屬的具體派生類(lèi); 只對(duì)多態(tài)類(lèi)型適用;只對(duì)多態(tài)類(lèi)型適用; 比虛函數(shù)動(dòng)態(tài)綁定的開(kāi)銷(xiāo)更大,因此應(yīng)僅對(duì)虛比虛函數(shù)動(dòng)態(tài)綁定的開(kāi)銷(xiāo)更大,因此應(yīng)僅對(duì)虛函數(shù)無(wú)法解決的問(wèn)題使用。函數(shù)無(wú)法解決的問(wèn)題使用。l 運(yùn)行時(shí)類(lèi)型識(shí)別的方式運(yùn)行時(shí)類(lèi)型識(shí)別的方式 用用dynamic_cast做類(lèi)型轉(zhuǎn)換的嘗試;做類(lèi)型轉(zhuǎn)換的嘗試; 用用typeid直接獲取類(lèi)型信息。直接獲取類(lèi)型信息。81dynamic_cast的使用深度探索l 語(yǔ)法形式語(yǔ)法形式dynamic_cast(表達(dá)式表達(dá)式)l 功能功能將基類(lèi)指針轉(zhuǎn)換為派生類(lèi)指針,將基類(lèi)引用轉(zhuǎn)換將基類(lèi)指針轉(zhuǎn)換為派生類(lèi)指針,將基類(lèi)引用轉(zhuǎn)換為派生類(lèi)引用;為派生類(lèi)引用;轉(zhuǎn)

49、換是有條件的轉(zhuǎn)換是有條件的如果指針(或引用)所指對(duì)象的實(shí)際類(lèi)型與轉(zhuǎn)如果指針(或引用)所指對(duì)象的實(shí)際類(lèi)型與轉(zhuǎn)換的目的類(lèi)型兼容,則轉(zhuǎn)換成功進(jìn)行;換的目的類(lèi)型兼容,則轉(zhuǎn)換成功進(jìn)行;否則如執(zhí)行的是指針類(lèi)型的轉(zhuǎn)換,則得到空指否則如執(zhí)行的是指針類(lèi)型的轉(zhuǎn)換,則得到空指針;如執(zhí)行的是引用類(lèi)型的轉(zhuǎn)換,則拋出異常。針;如執(zhí)行的是引用類(lèi)型的轉(zhuǎn)換,則拋出異常。82例8-9 dynamic_cast示例深度探索#include #include using namespace std;using namespace std;class Base class Base public:public:virtual void

50、 fun1() cout Base:fun1() endl; virtual void fun1() cout Base:fun1() endl; virtual Base() virtual Base() ;class Derived1: class Derived1: public Basepublic Base public:public:virtual void fun1() cout Derived1:fun1() endl; virtual void fun1() cout Derived1:fun1() endl; virtual void fun2() cout Derived

51、1:fun2() endl; virtual void fun2() cout Derived1:fun2() endl; ;class Derived2: class Derived2: public Derived1public Derived1 public:public:virtual void fun1() cout Derived2:fun1() endl; virtual void fun1() cout Derived2:fun1() endl; virtual void fun2() cout Derived2:fun2() endl; virtual void fun2()

52、 cout Derived2:fun2() fun1();b-fun1();/嘗試將嘗試將b b轉(zhuǎn)換為轉(zhuǎn)換為Derived1Derived1指針指針Derived1 Derived1 * *d = d = dynamic_castDerived1 dynamic_cast(b);(b);/判斷轉(zhuǎn)換是否成功判斷轉(zhuǎn)換是否成功if (d != 0) d-fun2();if (d != 0) d-fun2(); int main() int main() Base b;Base b;fun(&b);fun(&b);Derived1 d1;Derived1 d1;fun(&d1)

53、;fun(&d1);Derived2 d2;Derived2 d2;fun(&d2);fun(&d2);return 0;return 0; 運(yùn)行結(jié)果:運(yùn)行結(jié)果:Base:fun1()Derived1:fun1()Derived1:fun2()Derived2:fun1()Derived2:fun2()84typeid的使用深度探索l 語(yǔ)法形式語(yǔ)法形式 typeid ( 表達(dá)式表達(dá)式 ) typeid ( 類(lèi)型說(shuō)明符類(lèi)型說(shuō)明符 )l 功能功能 獲得表達(dá)式或類(lèi)型說(shuō)明符的類(lèi)型信息獲得表達(dá)式或類(lèi)型說(shuō)明符的類(lèi)型信息表達(dá)式有多態(tài)類(lèi)型時(shí),會(huì)被求值,并得到動(dòng)態(tài)類(lèi)型信息;表達(dá)式有多態(tài)類(lèi)

54、型時(shí),會(huì)被求值,并得到動(dòng)態(tài)類(lèi)型信息;否則,表達(dá)式不被求值,只能得到靜態(tài)的類(lèi)型信息。否則,表達(dá)式不被求值,只能得到靜態(tài)的類(lèi)型信息。 類(lèi)型信息用類(lèi)型信息用type_info對(duì)象表示對(duì)象表示type_info是是typeinfo頭文件中聲明的類(lèi);頭文件中聲明的類(lèi);typeid的結(jié)果是的結(jié)果是type_info類(lèi)型的常引用;類(lèi)型的常引用;可以用可以用type_info的重載的的重載的“=”、“!=”操作符比操作符比較兩類(lèi)型的異同;較兩類(lèi)型的異同;type_info的的name成員函數(shù)返回類(lèi)型名稱(chēng),類(lèi)型為成員函數(shù)返回類(lèi)型名稱(chēng),類(lèi)型為const char *。85例8-10 typeid示例深度探索#include #include #include #include using namespace std;using namespace std;class Base class Base public:public:virtual Base() virtual Base() ;class Derived: public Base ;class Derived: public Base ;86 void fun(Base void fun(Base * *b) b) /得到表示得到表示b b和和* *b b類(lèi)型信息的對(duì)象類(lèi)型信息的對(duì)象const typ

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論