版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第四章運(yùn)算符重載第一頁(yè),共八十一頁(yè),2022年,8月28日4.1什么是運(yùn)算符重載 C++為程序員提供了靈活的手段,讓程序員自己定義類,自己設(shè)計(jì)相應(yīng)的運(yùn)算符(必須在已有的運(yùn)算符基礎(chǔ)上設(shè)計(jì)),使之應(yīng)用于自己定義的類。與函數(shù)重載類似,對(duì)已有的運(yùn)算符賦予新的含義,用一個(gè)運(yùn)算符表示不同功能的運(yùn)算,這就是運(yùn)算符重載。 實(shí)際上,我們?cè)诖酥耙呀?jīng)使用了運(yùn)算符重載。如<<是C++的移位運(yùn)算符,它又與流對(duì)象cout配合作為流插入運(yùn)算符,這是C++對(duì)<<進(jìn)行了重載處理。第二頁(yè),共八十一頁(yè),2022年,8月28日運(yùn)算符重載的實(shí)質(zhì)運(yùn)算符重載是對(duì)已有的運(yùn)算符賦予多重含義。必要性C++中預(yù)定義的運(yùn)算符其運(yùn)算對(duì)象只能是基本數(shù)據(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ù)重載的選擇原則。第三頁(yè),共八十一頁(yè),2022年,8月28日 例4.1通過(guò)成員函數(shù)實(shí)現(xiàn)復(fù)數(shù)的加法。 classComplex {private: doublereal; doubleimag;public:
Complex(){real=0;imag=0;} Complex(doubler,doublei){real=r;imag=i;}
Complexcomplex_add(Complex&c2); voiddisplay(); };第四頁(yè),共八十一頁(yè),2022年,8月28日
ComplexComplex::complex_add(Complex&c2) {Complexc; c.real=real+c2.real;c.imag=imag+c2.image;returnc;}
voidComplex::display() {cout<<"("<<real<<","<<imag<<"i)"<<endl;} intmain() {Complexc1(3,4),c2(5,-10),c3;
c3=plex_add(c2); cout<<"c1=";c1.display(); cout<<"c2=";c2.display(); cout<<"c1+c2=";c3.display(); return0; }第五頁(yè),共八十一頁(yè),2022年,8月28日 在Complex類中定義了complex_add函數(shù)做加法,函數(shù)的參數(shù)是引用對(duì)象,作為一個(gè)加數(shù)。在函數(shù)里定義了臨時(shí)對(duì)象c,兩個(gè)賦值語(yǔ)句相當(dāng)于:c.real=this->real+c2.real;c.imag=this->imag+c2.imag; 在main函數(shù)中通過(guò)對(duì)象c1調(diào)用加法函數(shù),上面的語(yǔ)句相當(dāng)于: c.real=c1.real+c2.real;c.imag=c1.imag+c2.imag; 能否用+運(yùn)算符實(shí)現(xiàn)復(fù)數(shù)加法?第六頁(yè),共八十一頁(yè),2022年,8月28日4.2運(yùn)算符重載的方法 運(yùn)算符重載的方法是定義一個(gè)重載運(yùn)算符函數(shù),在需要時(shí)系統(tǒng)自動(dòng)調(diào)用該函數(shù),完成相應(yīng)的運(yùn)算。運(yùn)算符重載實(shí)質(zhì)上是函數(shù)的重載。運(yùn)算符重載函數(shù)的格式是:
數(shù)據(jù)類型operator運(yùn)算符(形參表) {重載處理} 數(shù)據(jù)類型:是重載函數(shù)值的數(shù)據(jù)類型。 operator是保留字 第七頁(yè),共八十一頁(yè),2022年,8月28日規(guī)則和限制C++中可以重載除下列運(yùn)算符外的所有運(yùn)算符:
..*::?:sizeof()只能重載C++語(yǔ)言中已有的運(yùn)算符,不可臆造新的。不改變?cè)\(yùn)算符的優(yōu)先級(jí)和結(jié)合性。不能改變操作數(shù)個(gè)數(shù)。經(jīng)重載的運(yùn)算符,其操作數(shù)中至少應(yīng)該有一個(gè)是自定義類型。第八頁(yè),共八十一頁(yè),2022年,8月28日兩種形式重載為類成員函數(shù)。重載為友元函數(shù)。第九頁(yè),共八十一頁(yè),2022年,8月28日運(yùn)算符函數(shù)聲明形式函數(shù)類型operator運(yùn)算符(形參){......}重載為類成員函數(shù)時(shí)
參數(shù)個(gè)數(shù)=原操作數(shù)個(gè)數(shù)-1 (后置++、--除外)重載為友元函數(shù)時(shí)參數(shù)個(gè)數(shù)=原操作數(shù)個(gè)數(shù),且至少應(yīng)該有一個(gè)自定義類型的形參。第十頁(yè),共八十一頁(yè),2022年,8月28日 不能重載的運(yùn)算符只有5個(gè):
.成員運(yùn)算符
.*成員指針運(yùn)算符
::域運(yùn)算符 sizeof長(zhǎng)度運(yùn)算符
?:條件運(yùn)算符 重載函數(shù)名是由operator和運(yùn)算符聯(lián)合組成。 復(fù)數(shù)加法運(yùn)算符重載函數(shù)原型可以是:Complexoperator+(Complex&c2); 例4.2重載運(yùn)算符+,用于兩個(gè)復(fù)數(shù)相加。第十一頁(yè),共八十一頁(yè),2022年,8月28日 分析:定義一個(gè)復(fù)數(shù)類,用成員函數(shù)實(shí)現(xiàn)加號(hào)的重載函數(shù)。兩個(gè)復(fù)數(shù)相加結(jié)果仍是復(fù)數(shù),所以函數(shù)的返回值的類型也是復(fù)數(shù)類。用成員函數(shù)實(shí)現(xiàn)運(yùn)算符重載函數(shù)時(shí),調(diào)用格式是“對(duì)象名.成員名”,此時(shí)對(duì)象就是一個(gè)參與運(yùn)算的操作數(shù),加法還需要另一個(gè)操作數(shù),這個(gè)操作數(shù)用函數(shù)的參數(shù)傳遞,參數(shù)的類型就是復(fù)數(shù)類。而運(yùn)算結(jié)果用函數(shù)值返回。第十二頁(yè),共八十一頁(yè),2022年,8月28日 classComplex {public: Complex(){real=0;imag=0;} Complex(doubler,doublei){real=r;imag=i;}
Complexoperator+(Complex&c2); voiddisplay(); private: doublereal; doubleimag; };第十三頁(yè),共八十一頁(yè),2022年,8月28日
ComplexComplex::operator+(Complex&c2) { Complexc; c.real=real+c2.real; c.imag=imag+c2.imag; returnc; }
voidComplex::display() { cout<<"("<<real<<","<<imag<<"i)"<<endl;}第十四頁(yè),共八十一頁(yè),2022年,8月28日 intmain() {Complexc1(3,4),c2(5,-10),c3;
c3=c1+c2; cout<<"c1=";c1.display(); cout<<"c2=";c2.display(); cout<<"c1+c2=";c3.display(); return0; }第十五頁(yè),共八十一頁(yè),2022年,8月28日 說(shuō)明: (1)用運(yùn)算符重載函數(shù)取代了例4.1中的加法成員函數(shù),從外觀上看函數(shù)體和函數(shù)返回值都是相同的。 (2)在主函數(shù)中的表達(dá)式c3=c2+c1取代了例4.1中的c3=plex_add(c2),編譯系統(tǒng)將表達(dá)式c3=c1+c2解釋為
c1.operator+(c2) 對(duì)象c1調(diào)用的重載函數(shù)operator+,以c2為實(shí)參計(jì)算兩個(gè)復(fù)數(shù)之和。第十六頁(yè),共八十一頁(yè),2022年,8月28日 請(qǐng)考慮在例4.2中能否用一個(gè)常量和一個(gè)復(fù)數(shù)相加?如 c3=3+c2;//錯(cuò)誤 應(yīng)該定義對(duì)象:ComplexC1(3.0,0): c3=C1+c2; 注意:運(yùn)算符重載后,其原來(lái)的功能仍然保留,編譯系統(tǒng)根據(jù)運(yùn)算表達(dá)式的上下文決定是否調(diào)用運(yùn)算符重載函數(shù)。 運(yùn)算符重載和類結(jié)合起來(lái),可以在C++中定義使用方便的新數(shù)據(jù)類型。第十七頁(yè),共八十一頁(yè),2022年,8月28日4.3重載運(yùn)算符的規(guī)則 (1)C++只允許已有的部分運(yùn)算符實(shí)施重載。 (2)不能重載的運(yùn)算符有五個(gè)。 (3)重載不改變操作數(shù)的個(gè)數(shù)。 (4)重載不改變運(yùn)算符的優(yōu)先級(jí)。 (5)運(yùn)算符重載函數(shù)不能帶默認(rèn)值參數(shù)。 (6)運(yùn)算符重載函數(shù)必須與自定義類型的對(duì)象聯(lián)合使用,其參數(shù)至少有一個(gè)類對(duì)象或類對(duì)象引用。 (7)C++默認(rèn)提供=和&運(yùn)算符重載。第十八頁(yè),共八十一頁(yè),2022年,8月28日(8)運(yùn)算符重載函數(shù)可以是類成員函數(shù)也可以是類的友元函數(shù),還可以是普通函數(shù)。(9)C++規(guī)定賦值運(yùn)算符、下標(biāo)運(yùn)算符、函數(shù)調(diào)用運(yùn)算符必須定義為類的成員函數(shù);而輸出流插入、輸入流提取、類型轉(zhuǎn)換運(yùn)算符不能定義為類的成員函數(shù)。第十九頁(yè),共八十一頁(yè),2022年,8月28日4.4運(yùn)算符重載函數(shù)作為類成員函數(shù)和友元函數(shù) 在例4.2程序中對(duì)運(yùn)算符+進(jìn)行了重載,該例將運(yùn)算符重載函數(shù)定義為復(fù)數(shù)類的成員函數(shù)。 從該程序中看到運(yùn)算符重載為成員函數(shù)時(shí),帶一個(gè)類類型的形參,而另一個(gè)加數(shù)就是對(duì)象自己。 例4.3將加法運(yùn)算符重載為適用于復(fù)數(shù)加法,重載函數(shù)作為類的友元函數(shù)。第二十頁(yè),共八十一頁(yè),2022年,8月28日#include<iostream.h>
classComplex {public:
Complex(){real=0;imag=0;}
Complex(doubler){real=r;imag=0;}
Complex
(doubler,doublei){real=r;imag=i;}
friendComplexoperator+(Complex&c1,Complex&c2); voiddisplay(); private: doublereal; doubleimag; };第二十一頁(yè),共八十一頁(yè),2022年,8月28日
Complexoperator+(Complex&c1,Complex&c2) {returnComplex(c1.real+c2.real,c1.imag+c2.imag);}
//顯式調(diào)用構(gòu)造函數(shù)
voidComplex::display() {cout<<"("<<real<<","<<imag<<"i)"<<endl;}第二十二頁(yè),共八十一頁(yè),2022年,8月28日 intmain() {Complexc1(3,4),c2(5,-10),c3; c3=c1+c2; cout<<"c1=";c1.display(); cout<<"c2=";c2.display(); cout<<"c1+c2=";c3.display(); return0; }第二十三頁(yè),共八十一頁(yè),2022年,8月28日 加法運(yùn)算符重載為友元函數(shù),C++在編譯時(shí)將表達(dá)式c1+c2解釋為 operator+(c1,c2) 即相當(dāng)于執(zhí)行以下函數(shù) Complexoperator+(Complex&c1,Complex&c2) {returnComplex(c1.real+c2.real,c1.imag+c2.imag); }
因?yàn)槠胀ê瘮?shù)是不能直接訪問(wèn)對(duì)象的私有成員,如果普通函數(shù)必須訪問(wèn)對(duì)象的私有成員,可調(diào)用類的公有成員函數(shù)訪問(wèn)對(duì)象的私有成員。這會(huì)降低效率。第二十四頁(yè),共八十一頁(yè),2022年,8月28日書上的錯(cuò)誤 如想將一個(gè)復(fù)數(shù)和一個(gè)整數(shù)相加,運(yùn)算符重載函數(shù)作為成員函數(shù)定義如下: ComplexComplex::operator+(int&i) {returnComplex(real+i,imag); } 注意在運(yùn)算符+的左側(cè)必須是Complex類對(duì)象,程序中可以寫成: c3=c2+n 不能寫成: c3=n+c2第二十五頁(yè),共八十一頁(yè),2022年,8月28日書上的錯(cuò)誤 如果要求在使用重載運(yùn)算符時(shí),運(yùn)算符左側(cè)操作數(shù)不是對(duì)象,就不能使用前面定義的運(yùn)算符重載函數(shù),可以將運(yùn)算符重載函數(shù)定義為友元函數(shù): friendComplexoperator+(int&i,Complex&c) {returnComplex(c.real+i,c.imag); } 友元函數(shù)不要求第一個(gè)參數(shù)必須是類類型,但是要求實(shí)參要與形參一一對(duì)應(yīng): c3=n+c2//順序正確 c3=c2+n//順序錯(cuò)誤第二十六頁(yè),共八十一頁(yè),2022年,8月28日 為了實(shí)現(xiàn)加法的交換率,必須定義兩個(gè)運(yùn)算符重載函數(shù),記住成員函數(shù)要求運(yùn)算符左側(cè)的操作數(shù)必須是自定義類型的對(duì)象,而友元函數(shù)沒有這個(gè)限制,可以用下面兩個(gè)組合中任意一個(gè): (1)成員函數(shù)(左操作數(shù)是對(duì)象,右操作數(shù)是非對(duì)象)、友元函數(shù)(左操作數(shù)是非對(duì)象,右操作數(shù)是對(duì)象) (2)友元函數(shù)(左操作數(shù)是對(duì)象,右操作數(shù)是非對(duì)象)、友元函數(shù)(左操作數(shù)是非對(duì)象,右操作數(shù)是對(duì)象)第二十七頁(yè),共八十一頁(yè),2022年,8月28日 由于使用友元會(huì)破壞類的封裝,要盡量將運(yùn)算符重載函數(shù)定義為成員函數(shù)。但考慮到各方面的因素,一般將單目運(yùn)算符重載為成員函數(shù),將雙目運(yùn)算符重載為友元函數(shù)。
VC++6.0的不帶后綴h的頭文件不支持把成員函數(shù)重載為友元函數(shù)。但VC++6.0帶后綴h的頭文件支持這項(xiàng)功能,所以要將程序中的語(yǔ)句: #include<iostream> usingnamespacestd; 改成: #include<iostream.h>
即可正常運(yùn)行。第二十八頁(yè),共八十一頁(yè),2022年,8月28日4.5重載雙目運(yùn)算符雙目的意思是運(yùn)算符左邊和右邊的操作數(shù)均參加運(yùn)算。如果要重載B為類成員函數(shù),使之能夠?qū)崿F(xiàn)表達(dá)式oprd1Boprd2,其中
oprd1為A類對(duì)象,則B應(yīng)被重載為A類的成員函數(shù),形參類型應(yīng)該是oprd2所屬的類型。經(jīng)重載后,表達(dá)式
oprd1Boprd2相當(dāng)于oprd1.operatorB(oprd2)。第二十九頁(yè),共八十一頁(yè),2022年,8月28日例4.4定義一個(gè)字符串類String,用來(lái)處理不定長(zhǎng)的字符串,重載相等、大于、小于關(guān)系運(yùn)算符,用于兩個(gè)字符串的等于、大于、小于的比較運(yùn)算。操作數(shù):兩個(gè)操作數(shù)都是字符串類的對(duì)象。規(guī)則:兩個(gè)字符串進(jìn)行比較。將“<”、“=”、“>”運(yùn)算重載為字符串類的成員函數(shù)。第三十頁(yè),共八十一頁(yè),2022年,8月28日 (1)先建立一個(gè)String類 #include<iostream.h> #include<string.h> classString//String是用戶自己指定的類名 {public: String(){p=NULL;} String(char*str); voiddisplay(); private: char*p; };第三十一頁(yè),共八十一頁(yè),2022年,8月28日 String::String(char*str) {p=str;} voidString::display() {cout<<p;} intmain() {Stringstring1("Hello"),string2("Book"); string1.display(); cout<<endl; string2.display(); return0; }第三十二頁(yè),共八十一頁(yè),2022年,8月28日 先編寫出簡(jiǎn)單的程序框架,編寫和調(diào)試都比較方便。構(gòu)造函數(shù)是把定義對(duì)象時(shí)的實(shí)參的地址賦予數(shù)據(jù)成員p,p是指向?qū)崊⒌闹羔?。程序?qū)崿F(xiàn)了建立對(duì)象、輸出字符串對(duì)象的功能。程序運(yùn)行結(jié)果分別輸出 Hello Book (2)有了這個(gè)基礎(chǔ)后,再增加所需的其他內(nèi)容,先重載大于運(yùn)算符。程序如下:第三十三頁(yè),共八十一頁(yè),2022年,8月28日 //本程序適用于VC++6.0 #include<iostream.h> #include<string.h> classString {public: String(){p=NULL;} String(char*str); voiddisplay();
friendbooloperator>(String&string1,String&string2);
private: char*p; }; String::String(char*str) {p=str;}第三十四頁(yè),共八十一頁(yè),2022年,8月28日 voidString::display() {cout<<p;}
booloperator>(String&string1,String&string2) {if(strcmp(string1.p,string2.p)>0) returntrue; elsereturnfalse; }
intmain() {Stringstring1("Hello"),string2("Book"); cout<<(string1>string2)<<endl; return0; }第三十五頁(yè),共八十一頁(yè),2022年,8月28日 運(yùn)算符重載函數(shù)定義為友元函數(shù),函數(shù)值是布爾類型,在函數(shù)中調(diào)用了strcmp庫(kù)函數(shù),string1.p指向“Hello”,string2.p指向“Book”,程序運(yùn)行結(jié)果是1。 (3)擴(kuò)展到對(duì)三個(gè)運(yùn)算符重載 在String類體中聲明三個(gè)重載函數(shù)是友元函數(shù),并編寫相應(yīng)的函數(shù)。第三十六頁(yè),共八十一頁(yè),2022年,8月28日 //本程序適用于VC++6.0 #include<iostream.h> #include<string.h> classString {public: String(){p=NULL;} String(char*str);
friendbooloperator>(String&string1,String&string2); friendbooloperator<(String&string1,String&string2); friendbooloperator==(String&string1,String&string2); voiddisplay();
private: char*p; };第三十七頁(yè),共八十一頁(yè),2022年,8月28日 String::String(char*str) {p=str;} voidString::display() {cout<<p;} booloperator>(String&string1,String&string2) {if(strcmp(string1.p,string2.p)>0) returntrue; else returnfalse; }第三十八頁(yè),共八十一頁(yè),2022年,8月28日 booloperator<(String&string1,String&string2) {if(strcmp(string1.p,string2.p)<0) returntrue; else returnfalse; } booloperator==(String&string1,String&string2) {if(strcmp(string1.p,string2.p)==0) returntrue; else returnfalse; }第三十九頁(yè),共八十一頁(yè),2022年,8月28日 intmain() {Stringstring1("Hello"),string2("Book"),string3("Computer"); cout<<(string1>string2)<<endl; cout<<(string1<string3)<<endl; cout<<(string1==string2)<<endl; return0; } 運(yùn)行結(jié)果為 1 0 0第四十頁(yè),共八十一頁(yè),2022年,8月28日4.6重載單目運(yùn)算符 單目運(yùn)行符只要一個(gè)操作數(shù),由于只有一個(gè)操作數(shù),重載函數(shù)最多只有一個(gè)參數(shù),如果將運(yùn)算符重載函數(shù)定義為成員函數(shù)還可以不用參數(shù)。 下面以自增運(yùn)算符++為例,學(xué)習(xí)單目運(yùn)算符的重載函數(shù)的編寫方法。 例4.5有一個(gè)Time類,數(shù)據(jù)成員有時(shí)、分、秒。要求模擬秒表,每次走一秒,滿60秒進(jìn)位,秒又從零開始計(jì)數(shù)。滿60分進(jìn)位,分又從零開始計(jì)數(shù)。輸出時(shí)、分和秒的值。第四十一頁(yè),共八十一頁(yè),2022年,8月28日 #include<iostream> usingnamespacestd; classTime {public: Time(){hour=0;minute=0;sec=0;} Time(inth,intm,ints):hour(h),minute(m),sec(s){} Timeoperator++(); voiddisplay(){cout<<hour<<":"<<minute<<":"<<sec<<endl;} private: inthour; intminute; intsec; };第四十二頁(yè),共八十一頁(yè),2022年,8月28日TimeTime::operator++() //前置單目運(yùn)算符重載函數(shù){ sec++; if(sec>=60) {sec=sec-60; minute++; if(minute>=60) { minute=minute-60; hour++; hour=hour%24; } }return*this;}43第四十三頁(yè),共八十一頁(yè),2022年,8月28日intmain() {Timetime1(23,59,0); for(inti=0;i<61;i++) {++time1; time1.display();} return0; }第四十四頁(yè),共八十一頁(yè),2022年,8月28日 C++中除了有前++外,還有后++。同樣的運(yùn)算符由于操作數(shù)的位置不同,含義也不同。怎樣區(qū)分前++和后++?C++給了一個(gè)方法,在自增或自減運(yùn)算符重載函數(shù)中,增加一個(gè)int形參。程序員可以選擇帶int形參的函數(shù)做后++,也可以選擇不帶int形參的函數(shù)做前++。 例4.6在例4.5的基礎(chǔ)上增加后++運(yùn)算符重載函數(shù)。第四十五頁(yè),共八十一頁(yè),2022年,8月28日 #include<iostream> usingnamespacestd; classTime {public: Time(){hour=0;minute=0;sec=0;} Time(inth,intm,ints):hour(h),minute(m),sec(s){}
Timeoperator++();
Timeoperator++(int);voiddisplay(){cout<<hour<<":"<<minute<<":"<<sec<<endl;} private: inthour;intminute; intsec; };第四十六頁(yè),共八十一頁(yè),2022年,8月28日TimeTime::operator++() //前置單目運(yùn)算符重載函數(shù){ sec++; if(sec>=60) {sec=sec-60; minute++; if(minute>=60) { minute=minute-60; hour++; hour=hour%24; } }return*this;}47第四十七頁(yè),共八十一頁(yè),2022年,8月28日 分析:后++運(yùn)算的含義是操作數(shù)先參加其他運(yùn)算后再自加。如 m=n++ 先將n的值賦予m,然后n再自加1。設(shè)計(jì)后++重載函數(shù)要遵循這個(gè)特性。 TimeTime::operator++(int) {Timetemp(*this);//保存修改前的對(duì)象做返回值 ++(*this); returntemp; }第四十八頁(yè),共八十一頁(yè),2022年,8月28日 intmain() {Timetime1(21,34,59),time2; cout<<"time1:"; time1.display(); ++time1; cout<<"++time1:"; time1.display(); time2=time1++; cout<<"time1++:"; time1.display(); cout<<"time2:"; time2.display(); return0; }程序運(yùn)行結(jié)果如下:Time1:21:34:59++Time1:21:35:0Time1++:21:35:1Time2:21:35:0第四十九頁(yè),共八十一頁(yè),2022年,8月28日4.7重載流插入運(yùn)算符和流提取運(yùn)算符 cin和cout分別是istream類和ostream類的對(duì)象。C++已經(jīng)對(duì)>>和<<移位運(yùn)算符進(jìn)行了重載,使它們分別成為流提取運(yùn)算符和流插入運(yùn)算符。用來(lái)輸入或輸出C++的標(biāo)準(zhǔn)類型數(shù)據(jù),所以要用#include<iostream>usingnamespacestd;把頭文件包含到程序中。 用戶自定義類型的數(shù)據(jù)不能直接用<<和>>輸出和輸入,如想用它們進(jìn)行輸入或輸出,程序員必須對(duì)它們重載。第五十頁(yè),共八十一頁(yè),2022年,8月28日 重載函數(shù)原型的格式如下: istream&operator>>(istream&,自定義類&); ostream&operator<<(ostream&,自定義類&); 從格式上看,>>重載函數(shù)和<<重載函數(shù)只能定義為友元函數(shù),不能定義為成員函數(shù),因?yàn)楹瘮?shù)有兩個(gè)形參,并且第一個(gè)形參不是自定義類型。第五十一頁(yè),共八十一頁(yè),2022年,8月28日4.7.1重載流插入運(yùn)算符“<<” 例4.7在例4.2的基礎(chǔ)上用<<重載函數(shù)輸出復(fù)數(shù)。 分析:在類中聲明<<重載函數(shù)是友元函數(shù) friendostream&operator<<(ostream&,Complex&); 在類外定義友元函數(shù): ostream&operator<<(ostream&output,Complex&c) {output<<"("<<c.real<<"+"<<c.imag<<"i)"<<endl; returnoutput; }第五十二頁(yè),共八十一頁(yè),2022年,8月28日
//本程序適用于VC++6.0 #include<iostream.h> intmain() {Complexc1(2,4),c2(6,10),c3; c3=c1+c2; cout<<c3; return0; }第五十三頁(yè),共八十一頁(yè),2022年,8月28日 分析C++怎樣處理”cout<<c3;”語(yǔ)句 運(yùn)算符的左邊是ostream的對(duì)象cout,右邊是程序員自定義類complex的對(duì)象c3,語(yǔ)句符合運(yùn)算符重載友元函數(shù)operator<<的形參類型要求,系統(tǒng)調(diào)用友元函數(shù),C++把這個(gè)語(yǔ)句解釋為: operator<<(cout,c3); 通過(guò)形參引用傳遞,函數(shù)中的output就是cout,函數(shù)中的c就是c3,函數(shù)就變成: { cout<<"("<<c3.real<<"+"<<c3.imag<<"i)"<<endl;returncout; }第五十四頁(yè),共八十一頁(yè),2022年,8月28日 returncout是將輸出流現(xiàn)狀返回。C++規(guī)定運(yùn)算符<<重載函數(shù)第一個(gè)參數(shù)和函數(shù)的類型必須是ostream類型的引用,目的是為了返回cout的當(dāng)前值,以便連續(xù)輸出。第五十五頁(yè),共八十一頁(yè),2022年,8月28日4.7.2重載流提取運(yùn)算符“>>” 例4.8在例4.7的基礎(chǔ)上增加流提取運(yùn)算符>>重載函數(shù),用cin>>輸入復(fù)數(shù),用cout<<輸出復(fù)數(shù)。 在類中聲明友元函數(shù): friendistream&operator>>(istream&,Complex&); 在類外定義函數(shù): istream&operator>>(istream&input,Complex&c) {cout<<"請(qǐng)輸入復(fù)數(shù)的實(shí)部和虛部:"; input>>c.real>>c.imag; returninput; }第五十六頁(yè),共八十一頁(yè),2022年,8月28日 intmain() {Complexc1,c2;
cin>>c1>>c2; cout<<"c1="<<c1<<endl; cout<<"c2="<<c2<<endl; return0; }
運(yùn)算符>>重載函數(shù)中的形參input是istream類對(duì)象引用,在執(zhí)行cin>>c1時(shí),調(diào)用operator>>函數(shù),將cin引用傳遞給input,input是cin的別名,同樣c是c1的別名。因此,input>>c.real>>c.imag;相當(dāng)于cin>>c1.real>>c1.imag。函數(shù)返回cin的新值。使程序可以用重載函數(shù)連續(xù)從輸入流提取數(shù)據(jù)給complex類對(duì)象。第五十七頁(yè),共八十一頁(yè),2022年,8月28日 程序邏輯上是正確的,但還有缺陷,如果輸入的虛部是負(fù)數(shù)時(shí),輸出的形式變成: c2=(4+-10i) 在負(fù)數(shù)前多個(gè)正號(hào)。可以對(duì)程序稍做修改:ostream&operator<<(ostream&output,Complex&c) {output<<"("<<c.real; if(c.imag>=0)output<<"+"; output<<c.imag<<"i)"<<endl; returnoutput; }第五十八頁(yè),共八十一頁(yè),2022年,8月28日 從本章例子中可以注意到,在運(yùn)算符重載中使用引用參數(shù)的重要性,用引用形參在調(diào)用函數(shù)時(shí),通過(guò)傳遞地址方式讓形參成為實(shí)參的別名,不用生成臨時(shí)變量,減少了時(shí)間和空間的開銷。此外,如重載函數(shù)的返回值是對(duì)象引用時(shí),返回的是對(duì)象,它可以出現(xiàn)在賦值號(hào)的左側(cè)而成為左值,可以被賦值或參與其他操作(如保留cout流的當(dāng)前值以便能連續(xù)使用<<輸出)。第五十九頁(yè),共八十一頁(yè),2022年,8月28日4.8.1標(biāo)準(zhǔn)類型數(shù)據(jù)間的轉(zhuǎn)換inti=6;i=7.5+i;編譯過(guò)程:7.5作為double型數(shù)處理求解表達(dá)式時(shí),將6轉(zhuǎn)換陳double,然后再和7.5相加得到的13.5的值向整型變量i賦值時(shí),先轉(zhuǎn)換為13再賦值這種轉(zhuǎn)換是c++編譯系統(tǒng)自動(dòng)完成的,稱為隱式類型轉(zhuǎn)換。第六十頁(yè),共八十一頁(yè),2022年,8月28日C++的顯式類型轉(zhuǎn)換,是一種人為的強(qiáng)制轉(zhuǎn)換。格式:類型名(數(shù)據(jù))例如:int(89.5)C語(yǔ)言中的采用形式(類型名)數(shù)據(jù)如:(int)89.5C++保留了c語(yǔ)言的用法,提倡用c++的方法第六十一頁(yè),共八十一頁(yè),2022年,8月28日4.8.2用轉(zhuǎn)換構(gòu)造函數(shù)進(jìn)行類型轉(zhuǎn)換作用:將一個(gè)其它類型的數(shù)據(jù)轉(zhuǎn)換成一個(gè)指定的類的對(duì)象。轉(zhuǎn)換構(gòu)造函數(shù)只有一個(gè)形參,如Complex(doubler){real=r;imag=0;} 其作用就是將double型的參數(shù)r轉(zhuǎn)換成Complex類的對(duì)象Complexc1(3.5);//建立一個(gè)對(duì)象,調(diào)用構(gòu)造函數(shù) 可以用聲明語(yǔ)句建立一個(gè)無(wú)名的Complex對(duì)象,如 Complex(3.6)//合法,但無(wú)法使用 可以在一個(gè)表達(dá)式中使用無(wú)名對(duì)象,如 c1=complex(3.6);//假設(shè)c1已被定義為Complex類的對(duì)象第六十二頁(yè),共八十一頁(yè),2022年,8月28日轉(zhuǎn)換構(gòu)造函數(shù)也是一種構(gòu)造函數(shù),它遵循構(gòu)造函數(shù)的一般規(guī)則。通常把有一個(gè)參數(shù)的構(gòu)造函數(shù)用作類型轉(zhuǎn)換,所以,稱為轉(zhuǎn)換構(gòu)造函數(shù)。注意: 轉(zhuǎn)換構(gòu)造函數(shù)只能有一個(gè)參數(shù)。如果有多個(gè)參數(shù),就不是轉(zhuǎn)換構(gòu)造函數(shù)。原因是:如果有多個(gè)參數(shù)的話,究竟是把哪個(gè)參數(shù)轉(zhuǎn)換成類的對(duì)象呢第六十三頁(yè),共八十一頁(yè),2022年,8月28日使用轉(zhuǎn)換構(gòu)造函數(shù)將一個(gè)指定的數(shù)據(jù)轉(zhuǎn)換成類的對(duì)象的方法如下:(1)先聲明一個(gè)類(如上面的Complex)。(2)在這個(gè)類中定義一個(gè)只有一個(gè)參數(shù)的構(gòu)造函數(shù),參數(shù)的類型是需要轉(zhuǎn)換的類型,在函數(shù)體中指定轉(zhuǎn)換的方法。(3)在該類的作用域內(nèi)可以用以下形式進(jìn)行類型轉(zhuǎn)換:
類名(指定類型的數(shù)據(jù))第六十四頁(yè),共八十一頁(yè),2022年,8月28日 不僅可以將一個(gè)標(biāo)準(zhǔn)類型數(shù)據(jù)轉(zhuǎn)換成類對(duì)象,也可以將另一個(gè)類的對(duì)象轉(zhuǎn)換成轉(zhuǎn)換構(gòu)造函數(shù)所在類的對(duì)象。 如:可以將一個(gè)學(xué)生類對(duì)象轉(zhuǎn)換成教師類對(duì)象,可以在Teacher類中寫出下面的構(gòu)造函數(shù): Teacher(Student&s){num=s.num;strcpy(name,);sex=s.sex;}
注意: 對(duì)象s中的num,name,sex必須是公有成員,否則不能被類外引用。第六十五頁(yè),共八十一頁(yè),2022年,8月28日4.8.3用類型轉(zhuǎn)換函數(shù)進(jìn)行類型轉(zhuǎn)換作用:將一個(gè)類的對(duì)象轉(zhuǎn)換成另一個(gè)類型的數(shù)據(jù)格式:
operator
類型名(){實(shí)現(xiàn)轉(zhuǎn)換的語(yǔ)句} 在函數(shù)名前面不能指定函數(shù)類型,函數(shù)沒有參數(shù) 返回值的類型是由函數(shù)名中指定的類型名來(lái)確定的。類型轉(zhuǎn)換函數(shù)只能作為成員函數(shù),因?yàn)檗D(zhuǎn)換的主體是本類的對(duì)象。不能作為友元函數(shù)或普通函數(shù)。第六十六頁(yè),共八十一頁(yè),2022年,8月28日轉(zhuǎn)換構(gòu)造函數(shù)和類型轉(zhuǎn)換運(yùn)算符的共同功能:當(dāng)需要的時(shí)候,編譯系統(tǒng)會(huì)自動(dòng)調(diào)用這些函數(shù),建立一個(gè)無(wú)名的臨時(shí)對(duì)象(或臨時(shí)變量)例:doubled1,d2;Complexc1,c2; 假設(shè)類中定義了類型轉(zhuǎn)換函數(shù) 對(duì)于表達(dá)式:d1=d2+c1;第六十七頁(yè),共八十一頁(yè),2022年,8月28日 編譯系統(tǒng)發(fā)現(xiàn)“+”左側(cè)的d2是double型,而右側(cè)的c1是Complex類對(duì)象,如果沒有對(duì)運(yùn)算符“+”進(jìn)行重載,就會(huì)檢查有無(wú)類型轉(zhuǎn)換函數(shù),結(jié)果發(fā)現(xiàn)有對(duì)double的重載函數(shù),就調(diào)用該函數(shù),把Complex類對(duì)象c1轉(zhuǎn)換為double型數(shù)據(jù),建立一個(gè)臨時(shí)的double變量,并與d2相加,最后將一個(gè)double型數(shù)據(jù)賦給d1。第六十八頁(yè),共八十一頁(yè),2022年,8月28日如果類中已定義轉(zhuǎn)換構(gòu)造函數(shù)并重載了運(yùn)算符“+”(作為Complex類的友元函數(shù)),但未對(duì)double定義類型轉(zhuǎn)換函數(shù)(或者說(shuō)未對(duì)double重載)對(duì)于表達(dá)式: c2=c1+d2; 編譯系統(tǒng)怎樣處理呢?第六十九頁(yè),共八十一頁(yè),2022年,8月28日它發(fā)現(xiàn)運(yùn)算符“+”左側(cè)的c1是Complex類對(duì)象,右側(cè)的d2是double型。編譯系統(tǒng)尋找有無(wú)對(duì)“+”的重載,發(fā)現(xiàn)有operator+函數(shù),但它是Complex類的友元函數(shù),要求兩個(gè)Complex類的形參,即只能實(shí)現(xiàn)兩個(gè)Complex類對(duì)象相加,而現(xiàn)在d2是double型,不合要求。在類中沒有對(duì)double進(jìn)行重載,因此不可能把c1轉(zhuǎn)換為double型數(shù)據(jù)然后相加。編譯系統(tǒng)就去找有無(wú)轉(zhuǎn)換構(gòu)造函數(shù),發(fā)現(xiàn)有,就調(diào)用轉(zhuǎn)換構(gòu)造函數(shù)Complex(d2),建立一個(gè)臨時(shí)的Complex類對(duì)象,在調(diào)用operator+函數(shù),將兩個(gè)復(fù)數(shù)相加,然后賦給c2。相當(dāng)于執(zhí)行表達(dá)式:c2=c1+Complex(d2)第七十頁(yè),共八十一頁(yè),2022年,8月28日例4.9使用類型轉(zhuǎn)換函數(shù)的簡(jiǎn)單例子#include<iostream>usingnamespacestd;classComplex{public:Complex(){real=0;imag=0;}Complex(doubler,doublei){real=r;imag=i;}operatordouble(){returnreal;}private:doublereal;doubleimag;};
intmain(){Complexc1(3,4),c2(5,-10),c3;doubled;d=2.5+c1;cout<<d<<endl;return0;}5.5第七十一頁(yè),共八十一頁(yè),2022年,8月28日分析:(1)如果在Complex類中沒有定義類型轉(zhuǎn)換函數(shù)operatordouble,程序編譯將會(huì)出錯(cuò)。因?yàn)椴荒軐?shí)現(xiàn)double數(shù)據(jù)類型與Complex類對(duì)象的相加。(2)如果在main函數(shù)中加一語(yǔ)句:c3=c2;編譯系統(tǒng)是把c2按Complex類對(duì)象處理,因?yàn)橘x值號(hào)兩側(cè)為同一類數(shù)據(jù),可以合法賦值。(3)如果在Complex類中聲明了重載運(yùn)算符“+”函數(shù)作為友元函數(shù),并在類外定義operator+函數(shù): Complexoperator+(Complexc1,Complexc2) {returnComplex(c1.real+c2.real,c1.imag+c2.imag);} c3=c1+c2;//有運(yùn)算符“+”重載,可以實(shí)現(xiàn)對(duì)象相加 d=c1+c2;//先相加,再通過(guò)對(duì)double的重載函數(shù)將臨時(shí)對(duì)象轉(zhuǎn)化為double,再賦值第七十二頁(yè),共八十一頁(yè),2022年,8月28日對(duì)類型的重載和對(duì)運(yùn)算符的重載的概念和方法相似重載函數(shù)都使用關(guān)鍵字operator,它的意思是“運(yùn)算符”。因此,通常把類型轉(zhuǎn)換函數(shù)也成為類型轉(zhuǎn)換運(yùn)算符函數(shù)由于它也是重載函數(shù),因此也稱為類型轉(zhuǎn)換運(yùn)算符重載函數(shù)(或稱強(qiáng)制類型轉(zhuǎn)換運(yùn)算符重載函數(shù))第七十三頁(yè),共八十一頁(yè),2022年,8月28日例4.10包含轉(zhuǎn)換構(gòu)造函數(shù)、運(yùn)算符重載函數(shù)和類型轉(zhuǎn)換函數(shù)的程序#include<iostream>usingnamespacestd;classComplex{pu
溫馨提示
- 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ù)覽,若沒有圖紙預(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 贈(zèng)錢協(xié)議書范本
- 銷售電熱器協(xié)議書
- 業(yè)績(jī)承包協(xié)議書
- 延保退款協(xié)議書
- 營(yíng)運(yùn)服務(wù)協(xié)議書
- 應(yīng)急住房協(xié)議書
- 2025浙江吉利控股集團(tuán)G-TOP博士專項(xiàng)招聘筆試重點(diǎn)題庫(kù)及答案解析
- 展位變更協(xié)議書
- 巡山記錄協(xié)議書
- 舞獅表演協(xié)議書
- 俄羅斯易貨貿(mào)易操作手冊(cè)2024年
- 個(gè)體工商戶入股協(xié)議書
- DB37-T 3080-2022特種設(shè)備作業(yè)人員配備要求
- DL∕T 1878-2018 燃煤電廠儲(chǔ)煤場(chǎng)盤點(diǎn)導(dǎo)則
- 科學(xué)精神與科學(xué)研究方法智慧樹知到期末考試答案2024年
- JB-T 14509-2023 反滲透海水淡化設(shè)備技術(shù)規(guī)范
- 種豬場(chǎng)人工授精技術(shù)推廣與應(yīng)用樣本
- 景觀模型設(shè)計(jì)與制作課件
- 工傷認(rèn)定申請(qǐng)表
- 信息化建設(shè)情況調(diào)查表
- 靜脈導(dǎo)管常見并發(fā)癥臨床護(hù)理實(shí)踐指南1
評(píng)論
0/150
提交評(píng)論