面向?qū)ο驝++8_第1頁(yè)
面向?qū)ο驝++8_第2頁(yè)
面向?qū)ο驝++8_第3頁(yè)
面向?qū)ο驝++8_第4頁(yè)
面向?qū)ο驝++8_第5頁(yè)
已閱讀5頁(yè),還剩49頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、1第八章第八章 多態(tài)性多態(tài)性C+語(yǔ)言程序設(shè)計(jì)C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉2本章主要內(nèi)容本章主要內(nèi)容l多態(tài)性多態(tài)性l運(yùn)算符重載運(yùn)算符重載l虛函數(shù)虛函數(shù)l純虛函數(shù)純虛函數(shù)l抽象類抽象類l深度探索深度探索C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉3多態(tài)性的概念多態(tài)性的概念l多態(tài)性是面向?qū)ο蟪绦蛟O(shè)計(jì)的重要特多態(tài)性是面向?qū)ο蟪绦蛟O(shè)計(jì)的重要特征之一。征之一。l多態(tài)性是指發(fā)出同樣的消息被不同類多態(tài)性是指發(fā)出同樣的消息被不同類型的對(duì)象接收時(shí)有可能導(dǎo)致完全不同型的對(duì)象接收時(shí)有可能導(dǎo)致完全不同的行為。的行為。l多態(tài)的實(shí)現(xiàn):多態(tài)的實(shí)現(xiàn): 函數(shù)重載 運(yùn)算符重載 虛函數(shù)C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉4問題舉例問題舉例復(fù)數(shù)的運(yùn)算復(fù)

2、數(shù)的運(yùn)算class Complex class Complex /復(fù)數(shù)類聲明復(fù)數(shù)類聲明public:public:Complex(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;運(yùn)算符重載C+語(yǔ)言程

3、序設(shè)計(jì)清華大學(xué) 鄭莉5問題舉例問題舉例復(fù)數(shù)的運(yù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)算的方法 重載重載“+”、“-”運(yùn)算符運(yùn)算符運(yùn)算符重載C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉6運(yùn)算符重載的實(shí)質(zhì)運(yùn)算符重載的實(shí)質(zhì)l運(yùn)算符重載是對(duì)已有的運(yùn)算符賦予多重含運(yùn)算符重載是對(duì)已有的運(yùn)算符賦予多重含義義l必要性必要性 C+中預(yù)定義的運(yùn)算符其運(yùn)算對(duì)象只能是基本數(shù)據(jù)類型,而不適用于用戶自定義類型(如類)l實(shí)現(xiàn)機(jī)制實(shí)現(xiàn)機(jī)制 將指定的運(yùn)算表達(dá)式轉(zhuǎn)化為對(duì)運(yùn)算符函數(shù)的調(diào)用,運(yùn)算對(duì)象轉(zhuǎn)化為運(yùn)算符函數(shù)的實(shí)參。 編譯系統(tǒng)對(duì)重載運(yùn)算符的選擇,遵循函數(shù)重載

4、的選擇原則。運(yùn)算符重載C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉7運(yùn)算符重載規(guī)則和限制規(guī)則和限制l可以重載可以重載C+中除下列運(yùn)算符外的所中除下列運(yùn)算符外的所有運(yùn)算符:有運(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)經(jīng)重載的運(yùn)算符,其操作數(shù)中至少應(yīng)該有一個(gè)是自定義類型。該有一個(gè)是自定義類型。C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉8兩種形式兩種形式l重載為類的非靜態(tài)成員函數(shù)重載為類的非靜態(tài)成員函數(shù)l重載為非

5、成員函數(shù)重載為非成員函數(shù)運(yùn)算符重載C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉9運(yùn)算符函數(shù)運(yùn)算符函數(shù)l聲明形式聲明形式函數(shù)類型 operator 運(yùn)算符(形參) .l重載為類成員函數(shù)時(shí)重載為類成員函數(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è)自定義類型的形參。且至少應(yīng)該有一個(gè)自定義類型的形參。運(yùn)算符重載C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉10運(yùn)算符成員函數(shù)的設(shè)計(jì)運(yùn)算符成員函數(shù)的設(shè)計(jì)l雙目運(yùn)算符雙目運(yùn)算符 B 如果要重載 B 為類成員函數(shù),使之能夠?qū)崿F(xiàn)表達(dá)式 oprd1 B o

6、prd2,其中 oprd1 為A 類對(duì)象,則 B 應(yīng)被重載為 A 類的成員函數(shù),形參類型應(yīng)該是 oprd2 所屬的類型。 經(jīng)重載后,表達(dá)式 oprd1 B oprd2 相當(dāng)于 oprd1.operator B(oprd2)運(yùn)算符重載C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉11運(yùn)算符重載 例例 8-1 將將“+”+”、“-”-”運(yùn)算重載為復(fù)數(shù)類運(yùn)算重載為復(fù)數(shù)類的成員函數(shù)。的成員函數(shù)。l 規(guī)則規(guī)則: 實(shí)部和虛部分別相加減。實(shí)部和虛部分別相加減。l 操作數(shù)操作數(shù): 兩個(gè)操作數(shù)都是復(fù)數(shù)類的對(duì)象。兩個(gè)操作數(shù)都是復(fù)數(shù)類的對(duì)象。#include #include using namespace std;using n

7、amespace std;class Complex class Complex /復(fù)數(shù)類定義復(fù)數(shù)類定義public:public:/外部接口外部接口Complex(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) /構(gòu)造函數(shù)構(gòu)造函數(shù)Complex operator + (const Complex &c2) const;Complex operator + (const Complex &c2) const;

8、/運(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() 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ù)虛部;12Complex C

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

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

11、 ( real , imag ) endl;endl; int main() int main() /主函數(shù)主函數(shù)Complex c1(5, 4), c2(2, 10), c3;Complex c1(5, 4), c2(2, 10), c3;/定義復(fù)定義復(fù)數(shù)類的對(duì)象數(shù)類的對(duì)象cout c1 = ; c1.display();cout c1 = ; c1.display();cout c2 = ; c2.display();cout c2 = ; c2.display();c3 = c3 = c1 - c2c1 - c2; ; /使用重載運(yùn)算符完成復(fù)數(shù)減法使用重載運(yùn)算符完成復(fù)數(shù)減法cout c3

12、 = 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.display();return 0;return 0; 14程序輸出的結(jié)果為:程序輸出的結(jié)果為:c1 = (5, 4)c2 = (2, 10)c3 = c1 - c2 = (3, -6)c3 = c1 + c2 = (7, 14)15C+語(yǔ)言

13、程序設(shè)計(jì)清華大學(xué) 鄭莉16運(yùn)算符成員函數(shù)的設(shè)計(jì)運(yùn)算符成員函數(shù)的設(shè)計(jì)l前置單目運(yùn)算符前置單目運(yùn)算符 U 如果要重載 U 為類成員函數(shù),使之能夠?qū)崿F(xiàn)表達(dá)式 U oprd,其中 oprd 為A類對(duì)象,則 U 應(yīng)被重載為 A 類的成員函數(shù),無(wú)形參。 經(jīng)重載后,表達(dá)式 U oprd 相當(dāng)于 oprd.operator U()運(yùn)算符重載C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉17運(yùn)算符成員函數(shù)的設(shè)計(jì)運(yùn)算符成員函數(shù)的設(shè)計(jì)l后置單目運(yùn)算符后置單目運(yùn)算符 +和和- 如果要重載 +或-為類成員函數(shù),使之能夠?qū)崿F(xiàn)表達(dá)式 oprd+ 或 oprd- ,其中 oprd 為A類對(duì)象,則 +或- 應(yīng)被重載為 A 類的成員函數(shù),且具有

14、一個(gè) int 類型形參。 經(jīng)重載后,表達(dá)式 oprd+ 相當(dāng)于 oprd.operator +(0)運(yùn)算符重載C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉18例例8-2l運(yùn)算符前置運(yùn)算符前置+和后置和后置+重載為時(shí)鐘類重載為時(shí)鐘類的成員函數(shù)。的成員函數(shù)。l前置單目運(yùn)算符,重載函數(shù)沒有形參,前置單目運(yùn)算符,重載函數(shù)沒有形參,對(duì)于后置單目運(yùn)算符,重載函數(shù)需要對(duì)于后置單目運(yùn)算符,重載函數(shù)需要有一個(gè)整型形參。有一個(gè)整型形參。l操作數(shù)是時(shí)鐘類的對(duì)象。操作數(shù)是時(shí)鐘類的對(duì)象。l實(shí)現(xiàn)時(shí)間增加實(shí)現(xiàn)時(shí)間增加1秒鐘。秒鐘。運(yùn)算符重載#include #include using namespace std;using names

15、pace std;class Clock class Clock /時(shí)鐘類聲明定義時(shí)鐘類聲明定義public:public:/外部接口外部接口Clock(int hour = 0, int minute = 0, int Clock(int hour = 0, int minute = 0, int second = 0);second = 0);void showTime() const;void showTime() const;Clock& operator + (); Clock& operator + (); /前置單目運(yùn)算符前置單目運(yùn)算符重載重載Clock oper

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

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

18、);this);/調(diào)用前置調(diào)用前置“+”+”運(yùn)算符運(yùn)算符return old;return old; 21/其它成員函數(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 Show myClock+: ;cout Show myClock+: ;( (myClock+myClock+).s

19、howTime();).showTime();cout Show +myClock: ;cout Show +myClock: ;( (+myClock+myClock).showTime();).showTime();return 0;return 0; 22程序運(yùn)行結(jié)果為:程序運(yùn)行結(jié)果為:First time output: 23:59:59First time output: 23:59:59Show myClock+: 23:59:59Show myClock+: 23:59:59Show +myClock: 0:0:1Show +myClock: 0:0:123C+語(yǔ)言程序設(shè)計(jì)清華大

20、學(xué) 鄭莉24運(yùn)算符非成員函數(shù)的設(shè)計(jì)運(yùn)算符非成員函數(shù)的設(shè)計(jì)l函數(shù)的形參代表依自左至右次序排列函數(shù)的形參代表依自左至右次序排列的各操作數(shù)。的各操作數(shù)。l后置單目運(yùn)算符后置單目運(yùn)算符 +和和-的重載函數(shù),的重載函數(shù),形參列表中要增加一個(gè)形參列表中要增加一個(gè)int,但不必寫,但不必寫形參名。形參名。l如果在運(yùn)算符的重載函數(shù)中需要操作如果在運(yùn)算符的重載函數(shù)中需要操作某類對(duì)象的私有成員,可以將此函數(shù)某類對(duì)象的私有成員,可以將此函數(shù)聲明為該類的友元。聲明為該類的友元。運(yùn)算符重載C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉25運(yùn)算符非成員函數(shù)的設(shè)計(jì)運(yùn)算符非成員函數(shù)的設(shè)計(jì)l雙目運(yùn)算符雙目運(yùn)算符 B重載后,重載后,表達(dá)式表達(dá)式

21、oprd1 B oprd2 等同于等同于operator B(oprd1,oprd2 )l前置單目運(yùn)算符前置單目運(yùn)算符 B重載后,重載后,表達(dá)式表達(dá)式 B oprd 等同于等同于operator B(oprd )l后置單目運(yùn)算符后置單目運(yùn)算符 +和和-重載后,重載后,表達(dá)式表達(dá)式 oprd B 等同于等同于operator B(oprd,0 )運(yùn)算符重載C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉26例例8-3l將將+ +、- -(雙目)重載為非成員函數(shù),(雙目)重載為非成員函數(shù),并將其聲明為復(fù)并將其聲明為復(fù)數(shù)類的友元,兩個(gè)操作數(shù)都是復(fù)數(shù)類的常引用。數(shù)類的友元,兩個(gè)操作數(shù)都是復(fù)數(shù)類的常引用。l將將(雙目)重

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

23、mespace std;class Complex class Complex /復(fù)數(shù)類定義復(fù)數(shù)類定義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, friend Complex operator + (const Complex &c1,

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

25、perator (ostream &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ù)虛部;27Complex Complex operator + operator + (const Complex &c1, const Complex &c2) (const Complex &c1, const Complex &

26、amp;c2) return 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);

27、 return Complex(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; 28C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉29靜態(tài)綁定與動(dòng)態(tài)綁定靜態(tài)綁定與動(dòng)態(tài)綁定l綁定綁定 程序自

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

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

30、rn w () const return w * * h; h; private:private:double w, h;double w, h;靜態(tài)綁定例30Rectangle: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) void fun(const void fun(const Point &sPoint &a

31、mp;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 = 0Area = 031#include#includeusing namespace std;using namespace std;class Point class Point

32、 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 Rectangle:public Point public:public:Rectangle(double

33、 x, double y, double w, double Rectangle(double x, double y, double w, double h);h);virtualvirtual double area() const return w double area() const return w * * h; h; private: private:double w, h;double w, h;/其他函數(shù)同上例其他函數(shù)同上例動(dòng)態(tài)綁定例 32void fun(const void fun(const Point &sPoint &s) ) cout Area =

34、 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 = 37533C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉34虛函數(shù)虛函數(shù)l虛函數(shù)是動(dòng)態(tài)綁定的基礎(chǔ)。虛函數(shù)是動(dòng)態(tài)綁定的基礎(chǔ)。l是非靜態(tài)的成員函數(shù)。是非靜態(tài)的成員函數(shù)。l在類的聲明中,在函數(shù)原型之前寫在類的聲明中,在函

35、數(shù)原型之前寫virtual。lvirtual 只用來(lái)說明類聲明中的原型,不能用在只用來(lái)說明類聲明中的原型,不能用在函數(shù)實(shí)現(xiàn)時(shí)。函數(shù)實(shí)現(xiàn)時(shí)。l具有繼承性,基類中聲明了虛函數(shù),派生類中具有繼承性,基類中聲明了虛函數(shù),派生類中無(wú)論是否說明,同原型函數(shù)都自動(dòng)為虛函數(shù)。無(wú)論是否說明,同原型函數(shù)都自動(dòng)為虛函數(shù)。l本質(zhì):不是重載聲明而是覆蓋。本質(zhì):不是重載聲明而是覆蓋。l調(diào)用方式:通過基類指針或引用,執(zhí)行時(shí)會(huì)調(diào)用方式:通過基類指針或引用,執(zhí)行時(shí)會(huì)根據(jù)根據(jù)指針指向的對(duì)象的類指針指向的對(duì)象的類,決定調(diào)用哪個(gè)函數(shù)。,決定調(diào)用哪個(gè)函數(shù)。虛 函 數(shù)C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉35例例 8-4#include #in

36、clude using namespace std;using namespace std;class Base1 /class Base1 /基類基類Base1Base1定義定義public:public:virtualvirtual void void displaydisplay() const;() const; /虛函數(shù)虛函數(shù);void Base1:display() const void Base1:display() const cout Base1:display() endl;cout Base1:display() endl; class Base2: public Bas

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

38、ass Derived: public Base2 public:public:void void displaydisplay() const; /() const; /覆蓋基類的虛函數(shù)覆蓋基類的虛函數(shù);void Derived:display() const void Derived:display() const cout Derived:display() endl;cout Derived:display() display();ptr-display();/對(duì)象指針對(duì)象指針-成員名成員名 36int main() int main() /主函數(shù)主函數(shù)Base1 base1;Base

39、1 base1;/定義定義Base1Base1類對(duì)象類對(duì)象Base2 base2;Base2 base2;/定義定義Base2Base2類對(duì)象類對(duì)象Derived derived;Derived derived;/定義定義DerivedDerived類對(duì)象類對(duì)象fun(&base1);fun(&base1);/用用Base1Base1對(duì)象的指針調(diào)用對(duì)象的指針調(diào)用funfun函數(shù)函數(shù)fun(&base2);fun(&base2);/用用Base2Base2對(duì)象的指針調(diào)用對(duì)象的指針調(diào)用funfun函數(shù)函數(shù)fun(&derived);fun(&deri

40、ved);/用用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()37C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉38虛析構(gòu)函數(shù)虛析構(gòu)函數(shù)為什么需要虛析構(gòu)函數(shù)?為什么需要虛析構(gòu)函數(shù)?l可能通過基類指針刪除派生類對(duì)象;可能通過基類指針刪除派生類對(duì)象;l如果你打算允許其他人通過基類指針如果你打算允許其他人通過基類指針調(diào)用對(duì)象的析構(gòu)函數(shù)(通過調(diào)用對(duì)象的析構(gòu)函數(shù)(通過delete這這樣做是正常的),就需要讓基類的析樣做是正常的),就需要讓基

41、類的析構(gòu)函數(shù)成為虛函數(shù),否則執(zhí)行構(gòu)函數(shù)成為虛函數(shù),否則執(zhí)行delete的結(jié)果是不確定的。的結(jié)果是不確定的。虛 函 數(shù)C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉39抽象類抽象類帶有純虛函數(shù)的類稱為抽象類帶有純虛函數(shù)的類稱為抽象類:class 類名類名 virtual 類型 函數(shù)名(參數(shù)表)=0; /純虛函數(shù)純虛函數(shù) .純虛函數(shù)與抽象類C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉40抽象類抽象類純虛函數(shù)與抽象類l作用作用 抽象類為抽象和設(shè)計(jì)的目的而聲明,將有關(guān)的數(shù)據(jù)和行為組織在一個(gè)繼承層次結(jié)構(gòu)中,保證派生類具有要求的行為。 對(duì)于暫時(shí)無(wú)法實(shí)現(xiàn)的函數(shù),可以聲明為純虛函數(shù),留給派生類去實(shí)現(xiàn)。l注意注意 抽象類只能作為基類來(lái)使用。

42、 不能聲明抽象類的對(duì)象。 構(gòu)造函數(shù)不能是虛函數(shù),析構(gòu)函數(shù)可以是虛函數(shù)。C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉41例例 8-5純虛函數(shù)與抽象類#include #include using namespace std;using namespace std;class Base1 /class Base1 /基類基類Base1Base1定義定義public:public:virtual void display() const = 0virtual void display() const = 0; ;/純虛函數(shù)純虛函數(shù);class Base2: public Base1 /class Base2: p

43、ublic Base1 /公有派生類公有派生類Base2Base2定義定義public:public:void void displaydisplay() const /() const /覆蓋基類的虛函數(shù)覆蓋基類的虛函數(shù)cout Base2:display() endl;cout Base2:display() endl; ;class Derived: public Base2 /class Derived: public Base2 /公有派生類公有派生類DerivedDerived定義定義public:public:void void displaydisplay() const /(

44、) const /覆蓋基類的虛函數(shù)覆蓋基類的虛函數(shù)cout Derived:display() endl;cout Derived:display() display();ptr-display();/對(duì)象指針對(duì)象指針-成員名成員名 int main() int main() /主函數(shù)主函數(shù)Base2 base2;Base2 base2; /定義定義Base2Base2類對(duì)象類對(duì)象Derived derived;Derived derived;/定義定義DerivedDerived類對(duì)象類對(duì)象fun(&base2);fun(&base2); /用用Base2Base2對(duì)象的指針

45、調(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é)果:Base2:display()Derived:display()42C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉多態(tài)類型與非多態(tài)類型多態(tài)類型與非多態(tài)類型l多態(tài)類型與非多態(tài)類型多態(tài)類型與非多態(tài)類型 有虛函數(shù)的類類型稱為多態(tài)類型 其它類型皆為非多態(tài)類型l二者的差異二者的差異 語(yǔ)言層面的差異l多態(tài)類型支持運(yùn)行時(shí)類型識(shí)別l多態(tài)類型對(duì)象占用額外的空間 設(shè)計(jì)原則上的差異4

46、3深 度 探 索C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉設(shè)計(jì)原則設(shè)計(jì)原則l多態(tài)類型多態(tài)類型 多態(tài)類型的析構(gòu)函數(shù)一般應(yīng)為虛函數(shù)l非多態(tài)類型非多態(tài)類型 非多態(tài)類型不宜作為公共基類l由于沒有利用動(dòng)態(tài)多態(tài)性,一般可以用組合,而無(wú)需用共有繼承;l如果繼承,則由于析構(gòu)函數(shù)不是虛函數(shù),刪除對(duì)象時(shí)所執(zhí)行操作與指針類型有關(guān),易引起混亂。 把不需被繼承的類型設(shè)定為非多態(tài)類型l由于成員函數(shù)都是靜態(tài)綁定,調(diào)用速度較快;l對(duì)象占用空間較小。44深 度 探 索C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉運(yùn)行時(shí)類型識(shí)別運(yùn)行時(shí)類型識(shí)別l運(yùn)行時(shí)類型識(shí)別運(yùn)行時(shí)類型識(shí)別 允許在運(yùn)行時(shí)通過基類指針(或引用)辨別對(duì)象所屬的具體派生類; 只對(duì)多態(tài)類型適用; 比

47、虛函數(shù)動(dòng)態(tài)綁定的開銷更大,因此應(yīng)僅對(duì)虛函數(shù)無(wú)法解決的問題使用。l運(yùn)行時(shí)類型識(shí)別的方式運(yùn)行時(shí)類型識(shí)別的方式 用dynamic_cast做類型轉(zhuǎn)換的嘗試; 用typeid直接獲取類型信息。45深 度 探 索C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉dynamic_cast的使用的使用l語(yǔ)法形式語(yǔ)法形式 dynamic_cast(表達(dá)式)l功能功能 將基類指針轉(zhuǎn)換為派生類指針,將基類引用轉(zhuǎn)換為派生類引用; 轉(zhuǎn)換是有條件的l如果指針(或引用)所指對(duì)象的實(shí)際類型與轉(zhuǎn)換的目的類型兼容,則轉(zhuǎn)換成功進(jìn)行;l否則如執(zhí)行的是指針類型的轉(zhuǎn)換,則得到空指針;如執(zhí)行的是引用類型的轉(zhuǎn)換,則拋出異常。46深 度 探 索C+語(yǔ)言程序設(shè)計(jì)

48、清華大學(xué) 鄭莉例例8-9 dynamic_cast示例示例#include #include using namespace std;using namespace std;class Base class Base public:public:virtual void fun1() cout Base:fun1() endl; virtual void fun1() cout Base:fun1() endl; virtual Base() virtual Base() ;class Derived1: class Derived1: public Base public Base publ

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

50、 Derived2:fun1() endl; virtual void fun1() cout Derived2:fun1() endl; virtual void fun2() cout Derived2:fun2() endl; virtual void fun2() 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

51、 (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);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(

52、)48C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉typeid的使用的使用l語(yǔ)法形式語(yǔ)法形式 typeid ( 表達(dá)式 ) typeid ( 類型說明符 )l功能功能 獲得表達(dá)式或類型說明符的類型信息l表達(dá)式有多態(tài)類型時(shí),會(huì)被求值,并得到動(dòng)態(tài)類型信息;l否則,表達(dá)式不被求值,只能得到靜態(tài)的類型信息。 類型信息用type_info對(duì)象表示ltype_info是typeinfo頭文件中聲明的類;ltypeid的結(jié)果是type_info類型的常引用;l可以用type_info的重載的“=”、“!=”操作符比較兩類型的異同;ltype_info的name成員函數(shù)返回類型名稱,類型為const char *。49深 度 探 索C+語(yǔ)言程序設(shè)計(jì)清華大學(xué) 鄭莉例例8-10 typeid示例示例#include #include #include #include using namespace std;using namespace std;class Base class Base public:public:virtual Base() virtual Base() ;c

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論