




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第八章 多態(tài)性,多態(tài)性作用 函數(shù)重載 運(yùn)算符重載 虛函數(shù) 抽象類 拷貝構(gòu)造函數(shù) 友元,8.1 程序的多態(tài)性,多態(tài)性:在程序中同一符號(hào)或名字在不同情況下具有不同解釋 多態(tài)性的兩種最基本形式 編譯時(shí)多態(tài)性:指在程序編譯階段即可確定下來(lái)的多態(tài)性 由重載機(jī)制實(shí)現(xiàn): 函數(shù)重載 運(yùn)算符重載 運(yùn)行時(shí)多態(tài)性:指必須等到程序動(dòng)態(tài)運(yùn)行時(shí)才可確定的多態(tài)性 由繼承結(jié)合虛函數(shù)的動(dòng)態(tài)綁定實(shí)現(xiàn),8.2 函數(shù)重載,函數(shù)重載:同一作用域中允許多個(gè)函數(shù)使用同一函數(shù)名,但函數(shù)原型的形式參數(shù)的個(gè)數(shù)或者對(duì)應(yīng)位置的類型不同 一、函數(shù)重載的方法 C語(yǔ)言不支持函數(shù)重載,所以每一個(gè)函數(shù)必須具有唯一的名字 例:求絕對(duì)值int abs(int);
2、整型 long labs(long);長(zhǎng)整型 float fabs(float);浮點(diǎn)型 C+的函數(shù)重載:編譯程序根據(jù)實(shí)際參數(shù)的個(gè)數(shù)與相應(yīng)位置的類型選擇調(diào)用哪一個(gè)版本的重載函數(shù),例1:,#include int abs(int x) / 整數(shù)類型數(shù)據(jù)的絕對(duì)值函數(shù) cout = 0 ? x : -x); double abs(double x) / 浮點(diǎn)類型數(shù)據(jù)的絕對(duì)值函數(shù) cout = 0.0 ? x : -x); long abs(long x) / 長(zhǎng)整數(shù)類型數(shù)據(jù)的絕對(duì)值函數(shù) cout = 0 ? x : -x); int main() cout abs(-5) n;/ 調(diào)用abs()的整
3、數(shù)版本 cout abs(-5L) n;/ 調(diào)用abs()的長(zhǎng)整數(shù)版本 cout abs(3.14) n;/ 調(diào)用abs()的浮點(diǎn)版本 return 0; ,二、函數(shù)重載的注意事項(xiàng),編譯程序選擇相應(yīng)的重載函數(shù)版本時(shí)函數(shù)返回值類型不起作用 例:int fun(int); double fun(int);不是重載函數(shù) 用typedef聲明的類型別名,并沒(méi)有創(chuàng)建新的數(shù)據(jù)類型 例:typedef double MONEY; double calculate(double income); MONEY calculate(MONEY income); 不是重載函數(shù) 不同參數(shù)傳遞方式無(wú)法區(qū)別重載函數(shù) 例:
4、void fun(int); void fun(int 不是重載函數(shù),三、函數(shù)重載的二義性原因: 1. 函數(shù)調(diào)用時(shí)參數(shù)的隱式類型轉(zhuǎn)換,函數(shù)調(diào)用時(shí),編譯程序選擇重載函數(shù)的原則:如果函數(shù)調(diào)用的實(shí)際參數(shù)類型與一個(gè)重載函數(shù)的形式參數(shù)類型完全匹配,則選擇調(diào)用該重載函數(shù);如果找不到與實(shí)際參數(shù)類型完全匹配的函數(shù)原型,但如果將實(shí)參類型轉(zhuǎn)換為更高級(jí)類型后能找到完全匹配,編譯程序?qū)⑦x擇該調(diào)用重載函數(shù)。 p234 例:int fun(int );fun(A); 隱式類型轉(zhuǎn)換是由編譯程序自動(dòng)完成,易引起函數(shù)重載的二義性,例2:,#include float abs(float x) return (x = 0 ? x
5、 : -x); double abs(double x) return (x = 0 ? x : -x); int main() cout abs(3.14) n;/ 調(diào)用abs(double)的版本 / cout abs(-5) n;/ 錯(cuò)誤,編譯程序無(wú)法確定調(diào)用abs()的哪一個(gè)版本 return 0; ,2. 在重載函數(shù)中使用缺省參數(shù)也可能造成二義性的例3:,#include int func(int i) return i; int func(int i, int j = 10) return i * j; int main() cout func(3, 4) n;/ 調(diào)用func(i
6、nt, int) / cout func(5) n;/ 錯(cuò)誤,編譯程序無(wú)法確定調(diào)用func()的哪一個(gè)版本 return 0; ,例4:指出下面程序的輸出結(jié)果。,#include ? void print(int x) coutCalling print(int) with x.n; void print(int x, int y) coutCalling print(int, int) with x, y .n; void print(double x) coutCalling print(double) with x.n; void main()運(yùn)行結(jié)果: print(800); prin
7、t(3.14159); print(3, 4); float f=1.5; print(f); ,Calling print(int) with 800,Calling print(double) with 3.14159,Calling print(int, int) with 3, 4,Calling print(double) with 1.5,四、構(gòu)造函數(shù)重載 為一個(gè)類提供了初始化對(duì)象的各種方法,#include class COMPLEX / 定義復(fù)數(shù)類COMPLEX的類界面 public: COMPLEX(double r = 0, double i = 0);/ 構(gòu)造函數(shù)一 CO
8、MPLEX(const COMPLEX,COMPLEX:COMPLEX(double r, double i) real = r; image = i; COMPLEX:COMPLEX(const COMPLEX/返回對(duì)象本身 ,COMPLEX COMPLEX:subtract(const COMPLEX ,8.3 拷貝構(gòu)造函數(shù),拷貝構(gòu)造函數(shù):以類類型本身做形式參數(shù),用一個(gè)已存在的該類對(duì)象初始化新創(chuàng)建的對(duì)象。 每一個(gè)類都必須有一個(gè)拷貝構(gòu)造函數(shù): 用戶根據(jù)自己的需要顯式定義 若用戶未提供,則該類使用由系統(tǒng)提供的缺省的拷貝構(gòu)造函數(shù):使用逐位復(fù)制方式利用另一個(gè)對(duì)象來(lái)初始化新創(chuàng)建對(duì)象。,拷貝構(gòu)造函數(shù)的
9、用途,在聲明語(yǔ)句中用一個(gè)對(duì)象初始化另一個(gè)對(duì)象class X X a;/調(diào)用X的普通構(gòu)造函數(shù) X b = a ; /調(diào)用X的拷貝構(gòu)造函數(shù); X b(a); /用a對(duì)象初始化b 將一個(gè)對(duì)象作為實(shí)參,以按值調(diào)用方式傳遞給被調(diào)用函數(shù)的形參對(duì)象void fun(X temp) fun(a); /a傳遞給fun函數(shù),創(chuàng)建 形參temp對(duì)象時(shí),調(diào)用X的拷貝構(gòu) 造函數(shù)用a對(duì)象初始化temp,temp 生存期結(jié)束時(shí),調(diào)用析構(gòu)函數(shù)釋放 生成一個(gè)臨時(shí)對(duì)象作為函數(shù)的返回結(jié)果 X fun2() b = fun2( ); X t; t - 臨時(shí)對(duì)象 - b 拷貝構(gòu)造函數(shù) 賦值運(yùn)算符 return t ; 當(dāng)函數(shù)返回一對(duì)象
10、時(shí),系統(tǒng)將自動(dòng)創(chuàng)建一個(gè)臨時(shí)對(duì)象來(lái)保存函數(shù)的返回值。此臨時(shí)對(duì)象在創(chuàng)建時(shí)調(diào)用拷貝構(gòu)造函數(shù),當(dāng)函數(shù)調(diào)用表達(dá)式結(jié)束后,調(diào)用析構(gòu)函數(shù)撤銷。,拷貝構(gòu)造函數(shù)的形式,以類類型本身做形式參數(shù), 該參數(shù)傳遞方式為按引用調(diào)用:使形參為實(shí)參的別名,避免在函數(shù)調(diào)用過(guò)程中生成形參副本 該形參一般聲明為const:因?yàn)榘匆谜{(diào)用是雙向的,為確保在拷貝構(gòu)造函數(shù)中不修改實(shí)參的值,所以用const 例如:X:X(const X ,例:,#include class FOO public:FOO(int i) cout Constructing.n; pointer = new int; *pointer = i; FOO(con
11、st FOO,void display(FOO obj) cout obj.get() n; return; int main() FOO obj1(15); FOO obj2 = obj1;/ 調(diào)用拷貝構(gòu)造函數(shù) display(obj2); / 調(diào)用拷貝構(gòu)造函數(shù)用實(shí)參obj2初始化形參obj return 0; 運(yùn)行結(jié)果: Constructing. Copy constructing. Copy constructing. 15 Destructing. Destructing. Destructing.,例2,#include #include class NAME public:NAM
12、E() string = NULL; cout Constructing.n; NAME() cout Destructing.n; if (string != NULL) delete string; void show()cout string n; void set(char* s) if (string!=NULL)delete string; string = new charstrlen(s) + 1; if (string!=NULL)strcpy(string, s); private: char* string; ;,NAME get_name() NAMEtemp_obj;
13、/ chartemp_str250; / cout temp_str; temp_obj.set(temp_str); / return temp_obj; / / void main() NAME myname; myname = get_name(); myname.show(); ,運(yùn)行結(jié)果: Constructing.myname的構(gòu)造 Constructing.temp_obj的構(gòu)造 Input your name: Lee Destructing.釋放temp_obj,delete string Destructing.函數(shù)返回的臨時(shí)對(duì)象被釋放 Null pointer assig
14、nmentdelete出問(wèn)題 (此行輸出的字符串是不確定的?。?Destructing.myname被釋放 Null pointer assignmentdelete出問(wèn)題,釋放局部變量temp_obj:new分配的2000H空間被釋放 3. 臨時(shí)對(duì)象賦給myname, myname.string的值置為2000H 4. 撤銷臨時(shí)對(duì)象,動(dòng)態(tài)分配的2000H空間已釋放,再釋放會(huì)出問(wèn)題 5. myname.show()輸出2000H上的內(nèi)容,不確定 6. 撤銷myname,delete出問(wèn)題,修改:加入拷貝構(gòu)造函數(shù)的定義,NAME:NAME(const NAME get_name函數(shù)返回, 創(chuàng)建臨
15、時(shí)對(duì)象,調(diào)用拷 貝構(gòu)造函數(shù) temp_obj.string 臨時(shí)對(duì)象.string,2000H,3000H,運(yùn)行結(jié)果: Constructing. Constructing. Input your name: Lee Destructing. Destructing. Lee Destructing.,8.4 運(yùn)算符重載一、運(yùn)算符重載,定義:在不同情況下對(duì)同樣的運(yùn)算符做不同的解釋 運(yùn)算符函數(shù) 二元運(yùn)算符是一個(gè)具有兩個(gè)參數(shù)的函數(shù) 一元運(yùn)算符是一個(gè)具有一個(gè)參數(shù)的函數(shù) 不能重載的運(yùn)算符: : .*?:#sizeof,二、類成員運(yùn)算符重載,一般形式: 類型 類名:operator (參數(shù)表) / 運(yùn)算
16、符函數(shù)體 例:p243 程序8.4.1 class COMPLEX public:COMPLEX(double r = 0, double i = 0);/ 構(gòu)造函數(shù) COMPLEX(const COMPLEX,int main() COMPLEX c1(1, 2);/ 定義一個(gè)值為1 + 2i的復(fù)數(shù)c1 COMPLEX c2(2);/ 定義一個(gè)值為2的復(fù)數(shù)c2 COMPLEX c3(c1);/ 用COMPLEX(const COMPLEX ,注意:,當(dāng)重載二元運(yùn)算符,運(yùn)算符成員函數(shù)只需顯式傳遞一個(gè)參數(shù),這是二元運(yùn)算符的右操作數(shù),而左操作數(shù)則是該類對(duì)象本身,用this指針隱式傳遞。 c1 =
17、c2 + c3 ; c1 = c2.operator +(c3); 當(dāng)重載一元運(yùn)算符,運(yùn)算符成員函數(shù)沒(méi)有參數(shù),其使用隱式傳遞的this指針做參數(shù)。,三、重載賦值運(yùn)算符=,類的賦值運(yùn)算符=可以被重載,但重載的賦值運(yùn)算符不能被繼承。 若用戶沒(méi)有為一個(gè)類重載賦值運(yùn)算符時(shí),編譯程序?qū)⑸梢粋€(gè)缺省的賦值運(yùn)算符,把源對(duì)象逐位地拷貝到目標(biāo)對(duì)象 c1 = c2 ; 拷貝構(gòu)造函數(shù)與賦值運(yùn)算符的區(qū)別 拷貝構(gòu)造函數(shù)要?jiǎng)?chuàng)建一個(gè)新對(duì)象 賦值運(yùn)算符則是改變一個(gè)已存在的對(duì)象的值,四、例:,#include class STRING private:int length; char *Buffer; public:STRIN
18、G(); STRING(const char *str); STRING(); ; STRING:STRING() length = 0; Buffer = NULL; STRING:STRING(const char *str) length = strlen(str); Buffer = new charlength+1; if (Buffer!=NULL) strcpy(Buffer,str); STRING:STRING() if (Buffer) delete Buffer; ,void main() STRING aString(This); STRING bString(That
19、); aString = bString; aString: length Buffer bString: length Buffer 賦值后aString的數(shù)據(jù)成員Bufer原來(lái)指向的字符串所占用的存儲(chǔ)塊永久丟失,解決方法:重載賦值運(yùn)算符 void STRING:operator=(const STRING ,五、友元,友元(friend)關(guān)系允許類的設(shè)計(jì)者選擇出一組其他的類或函數(shù),使得它們可以訪問(wèn)該類的私有和受保護(hù)成員。 在類的聲明中,用friend聲明的函數(shù)或類,即是該類的友元 一個(gè)類的友元可以是: 外部函數(shù)(不屬于任何類的函數(shù)) 另一個(gè)類 其他類的成員函數(shù) 友元破壞了封裝性,不可濫用,
20、例1:外部函數(shù)做友元,/ 類VALUE中定義了一個(gè)友元函數(shù)set(), / 注意set()不是該類的成員函數(shù) class VALUE public: /聲明set()為VALUE的友元 friend void set(VALUE obj, int x); private: int value; ; / 實(shí)現(xiàn)友元函數(shù)set() void set(VALUE obj, int x) obj.value = x;/ set()可以象VALUE成員函數(shù)一樣訪 / 問(wèn)obj的私有成員 return; ,例2:另一個(gè)類做友元,class Y;/ Y類的引用性聲明語(yǔ)句 class X public:frie
21、nd Y;/ 把Y類聲明為X類的友元,則Y類 /的所有成員函數(shù)都是X的友元 private:int k ; void m_Xfunc( ); ; class Y public: void m_Yfunc( X / Y類的成員函數(shù)是X的友元,可以訪問(wèn) / X的私友和受保護(hù)的成員 ,例3:其他類的成員函數(shù)做友元,class Y public: void Yfunc( ); ; class X public:friend void Y:Yfunc( ); / 把Y類的Yfunc函數(shù)聲明為X類的友元 private:int k ; void m_Xfunc( ); ; void Y:Yfunc( X
22、/ 該函數(shù)是X的友元,可以訪問(wèn) / X的私友和受保護(hù)的成員 ,六、友元運(yùn)算符重載 1. 類成員函數(shù)運(yùn)算符重載引起的問(wèn)題,例: y+30; 合法調(diào)用y.operator+(30) 30+y; 則不合法,因?yàn)樽蟛僮鲾?shù)不是該類的對(duì)象,因此無(wú)法調(diào)用該類重載的運(yùn)算符 類成員函數(shù)運(yùn)算符重載函數(shù)在使用時(shí),二元運(yùn)算符的左操作數(shù)必須為該類對(duì)象,否則出錯(cuò),2. 友元運(yùn)算符重載,參數(shù)規(guī)則: 一元運(yùn)算符必須顯式聲明一個(gè)參數(shù) 二元運(yùn)算符必須顯式聲明二個(gè)參數(shù) 不能做友元重載的運(yùn)算符 =( ) - 友元函數(shù)不是該類的成員,因此在友元函數(shù)中不能使用this指針,例:,#include class INTEGER public
23、: / 構(gòu)造函數(shù) INTEGER(int i = 0) value = i; return; / 拷貝構(gòu)造函數(shù) INTEGER(const INTEGER ,/ 用友元函數(shù)重載加法運(yùn)算符 friend INTEGER operator +(INTEGER left, INTEGER right) INTEGER temp; temp.value = left.value + right.value; return temp; private:int value;/ 私有數(shù)據(jù) ; void main() INTEGER x(10);/ 定義整數(shù)對(duì)象,用構(gòu)造函數(shù)來(lái)初始化 INTEGER y = x
24、;/ 定義整數(shù)對(duì)象,用拷貝構(gòu)造函數(shù)來(lái)初始化 INTEGER z;/ 定義整數(shù)對(duì)象,用構(gòu)造函數(shù)的缺省參數(shù)初始化 y = x + 2;/ 合法調(diào)用 z = 30 + y;/ 也是合法的調(diào)用 ,七、運(yùn)算符重載的其他規(guī)則,重載運(yùn)算符無(wú)法改變?nèi)魏芜\(yùn)算符的優(yōu)先級(jí)與結(jié)合性質(zhì); 重載運(yùn)算符不可改變運(yùn)算符的操作數(shù)個(gè)數(shù); 重載運(yùn)算符不可使用缺省參數(shù); 除了賦值運(yùn)算外,重載運(yùn)算符可由派生類繼承下去; 運(yùn)算符=、()、和-可作為類成員運(yùn)算符,但不可作為友元運(yùn)算符。,8.5 虛函數(shù) 一、綁定,綁定:將一個(gè)函數(shù)調(diào)用鏈接上相應(yīng)的函數(shù)體代碼的過(guò)程 綁定的兩種形式: 靜態(tài)綁定(早期綁定):在編譯階段綁定 缺省的函數(shù)調(diào)用方式 動(dòng)
25、態(tài)綁定(晚期綁定):在程序運(yùn)行階段綁定,二、虛函數(shù),虛函數(shù)是類中被冠以virtual的成員函數(shù) 虛函數(shù)在公有繼承結(jié)構(gòu)中在一個(gè)或多個(gè)派生類中被重定義,在被調(diào)用過(guò)程中,通過(guò)指向基類的指針實(shí)現(xiàn)動(dòng)態(tài)綁定,例1:,#include class BASE public: void who( ) coutwho(); p= / 基類指針可指向派生類對(duì)象 ,輸出結(jié)果:BASE BASE不管p指向什么對(duì)象,通過(guò)p三次調(diào) BASE用的都是基類的who函數(shù) 原因:普通成員函數(shù)的調(diào)用采用的是靜態(tài)綁定 通過(guò)指針引起的普通成員函數(shù)調(diào)用,僅僅與指針(或引用)的基類型有關(guān),而與此刻該指針正在指向什么對(duì)象無(wú)關(guān),例2:希望p-w
26、ho();依賴于運(yùn)行時(shí)p所指向的對(duì)象,則基類修改為:,class BASE public: virtual void who( ) cout“BASEn”; ; 把基類中的who函數(shù)定義成虛函數(shù),實(shí)現(xiàn)動(dòng)態(tài)綁定 輸出結(jié)果:BASE First Derivation Second Derivation 基類的虛函數(shù)定義了一種接口,在派生類中為此接口定義不同的實(shí)現(xiàn)版本,由于虛函數(shù)的解釋機(jī)制,實(shí)現(xiàn)“單界面、多實(shí)現(xiàn)版本”的思想,在運(yùn)行時(shí)刻才將函數(shù)與不同實(shí)現(xiàn)版本進(jìn)行匹配 運(yùn)行時(shí)的多態(tài)性,虛函數(shù)的說(shuō)明,用虛函數(shù)實(shí)現(xiàn)動(dòng)態(tài)綁定的關(guān)鍵:必須用指向基類的指針來(lái)訪問(wèn)虛函數(shù) 若一函數(shù)是類中的虛函數(shù),則稱該函數(shù)具有虛特性 在派生類中重定義從基類中繼承過(guò)來(lái)的函數(shù):函數(shù)原型保持不變 僅僅返回類型不同,其余相同,錯(cuò)誤 函數(shù)原型不同,僅函數(shù)名相同,這是一般的函數(shù)重載,虛特性丟失 當(dāng)一個(gè)派生類沒(méi)有重新定義虛函數(shù)時(shí),則使用其基類定義的虛函數(shù)版本,例3:,#include class BASE public: virtual void f1( ) virtual void f2( ) v
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝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ù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 【正版授權(quán)】 IEC 60068-2-83:2025 EN-FR Environmental testing - Part 2-83: Tests - Test Tf: Solderability testing of electronic components for surface mounting devices (SMD) by the wettin
- 【正版授權(quán)】 IEC/IEEE 80005-1:2019/AMD1:2022 EN-FR Amendment 1 - Utility connections in port - Part 1: High voltage shore connection (HVSC) systems - General requirements
- 2025至2030中國(guó)甲硫氨酸甲磺酰氯行業(yè)產(chǎn)業(yè)運(yùn)行態(tài)勢(shì)及投資規(guī)劃深度研究報(bào)告
- 2025至2030中國(guó)理發(fā)行業(yè)深度研究及發(fā)展前景投資評(píng)估分析
- 成人推拿培訓(xùn)課件
- 學(xué)習(xí)動(dòng)力與教學(xué)效果的關(guān)聯(lián)性研究
- 企業(yè)智慧交通系統(tǒng)解決方案的研究與實(shí)踐
- 教育行業(yè)勞動(dòng)法規(guī)定解讀
- 兒童健康教育的全面普及與提高研究
- 企業(yè)與政府協(xié)作推動(dòng)的智慧城市治理策略研究
- 物業(yè)經(jīng)理接待日制度
- 數(shù)獨(dú)教案-完整版
- 易制毒、易制爆化學(xué)品安全培訓(xùn)
- 后廚管理制度與章程內(nèi)容
- 【人教版化學(xué)】選擇性必修2 知識(shí)點(diǎn)默寫小紙條(空白默寫版)
- 情景與情境的區(qū)別與聯(lián)系
- 公務(wù)員考試經(jīng)驗(yàn)分享培訓(xùn)課件
- (高級(jí))數(shù)據(jù)安全管理員職業(yè)技能鑒定考試題庫(kù)-實(shí)操題
- 初三化學(xué)上冊(cè)第一單元測(cè)試題(含答案)
- 移動(dòng)通信網(wǎng)絡(luò)優(yōu)化服務(wù)合同
- (正式版)SH∕T 3548-2024 石油化工涂料防腐蝕工程施工及驗(yàn)收規(guī)范
評(píng)論
0/150
提交評(píng)論