第十八章運(yùn)算符重載_第1頁
已閱讀1頁,還剩104頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、1,第十八章 運(yùn)算符重載,,2,本章主要內(nèi)容,運(yùn)算符重載的需要性重載運(yùn)算符作友元函數(shù)運(yùn)算符作成員函數(shù)增量運(yùn)算符重載轉(zhuǎn)換運(yùn)算符重載賦值運(yùn)算符重載,,3,C++認(rèn)為用戶定義的數(shù)據(jù)類型就像基本數(shù)據(jù)類型int和char一樣有效。運(yùn)算符(如+, -,*,/)是為基本數(shù)據(jù)類型定義的,為什么不允許使之適用于用戶定義類型呢?例如: class A { public: A(int x)

2、 { a=x; } // }; A a(5),b(10),c; c=a+b; //類對象也應(yīng)能運(yùn)算運(yùn)算符重載可以改進(jìn)可讀性,但不是非有不可。,4,,多態(tài)性的實(shí)現(xiàn):函數(shù)重載虛函數(shù)運(yùn)算符重載在基本類型上,系統(tǒng)提供了許多預(yù)定義的運(yùn)算符(如+、-、*、/)。,5,問題舉例——復(fù)數(shù)的運(yùn)算,class complex//復(fù)數(shù)類聲明{public:

3、complex(double r=0.0,double i=0.0){real=r;imag=i;}void display();//顯示復(fù)數(shù)的值private:double real;double imag;};,用“+”、“-”能夠?qū)崿F(xiàn)復(fù)數(shù)的加減運(yùn)算嗎?實(shí)現(xiàn)復(fù)數(shù)加減運(yùn)算的方法 ——重載“+”、“-”運(yùn)算符必要性C++中預(yù)定義的運(yùn)算符其運(yùn)算對象只能是基本數(shù)據(jù)類型,而不適用于用戶自定義類型

4、(如類)。運(yùn)算符重載可提高程序的可讀性。,下列例子計(jì)算應(yīng)付給的人民幣,分別用了成員函數(shù)和運(yùn)算符成員函數(shù)兩種方法 class RMB{ public: RMB(double d){yuan=d; jf=(d-yuan)/100; } RMB interest(double rate); //計(jì)算利息 RMB add(rmb d); //人民幣加

5、 RMB operator + (RMB d){ //人民幣加的運(yùn)算符重載 return RMB(yuan+d.yuan+(jf+d.jf)/100;} RMB operator * (double rate){ return RMB((yuan+jf/100)*rate);} private: unsigned int yuan;

6、 // 元 unsigned int jf; // 角分};,RMB RMB::interest(double rate){ return RMB((yuan+jf)/100.0) * rate);}RMB RMB::add(RMB d){ return RMB(yuan+d.yuan+jf/100.0+d.jf/100.0);}//以下是計(jì)算應(yīng)付人民幣的兩個(gè)版本RMB e

7、xpense1(RMB principle,double rate){ RMB interest = principle.interest(rate); return principle.add(interest);}RMB expense2(RMB principle,double rate){ RMB interest = principle * rate; return principl

8、e + interest;},9,void main(){ RMB x = 10000.0; double yrate = 0.035; expense1(x,yrate).display(); expense2(x,yrate).display();} 運(yùn)行結(jié)果為: 20350 10350 expense()的兩個(gè)版本都可以計(jì)算應(yīng)付人民幣,運(yùn)行結(jié)果相同。expense2()可讀性

9、更好一點(diǎn),它符合我們計(jì)算用+, *運(yùn)算符的習(xí)慣。如果不定義運(yùn)算符重載,則expense2()中principal * rate和principal+interest是非法的。因?yàn)閰⒓舆\(yùn)算的是類對象而不是浮點(diǎn)值。,10,運(yùn)算符重載的實(shí)質(zhì),運(yùn)算符重載是對已有的運(yùn)算符賦予多重含義。實(shí)現(xiàn)機(jī)制運(yùn)算符重載的實(shí)質(zhì)就是函數(shù)重載:每個(gè)運(yùn)算符對應(yīng)各自的運(yùn)算符函數(shù),根據(jù)操作數(shù)的不同調(diào)用不同的同名函數(shù)。將指定的運(yùn)算表達(dá)式轉(zhuǎn)化為對運(yùn)算符函數(shù)的調(diào)用,運(yùn)算對

10、象轉(zhuǎn)化為運(yùn)算符函數(shù)的實(shí)參。,11,規(guī)則和限制,編譯系統(tǒng)對重載運(yùn)算符的選擇,遵循函數(shù)重載的選擇原則。可以重載C++中除下列運(yùn)算符外的所有運(yùn)算符:. .* .> :: ?:只能重載C++語言中已有的運(yùn)算符,不可臆造新的。不改變原運(yùn)算符的優(yōu)先級和結(jié)合性。不能改變操作數(shù)個(gè)數(shù)。經(jīng)重載的運(yùn)算符,其操作數(shù)中至少應(yīng)該有一個(gè)是自定義類的對象或是對類的對象的引用。,12,運(yùn)算符重載的兩種形式,重載為類的友元函數(shù):f

11、riend 類型 operator 運(yùn)算符(形參表) { 函數(shù)體 }重載為類的成員函數(shù):類型 operator 運(yùn)算符(形參表) { 函數(shù)體 },13,如何重載運(yùn)算符,運(yùn)算符是在C++系統(tǒng)內(nèi)部定義的,具有特定語法規(guī)則,如參數(shù)說明,運(yùn)算順序,優(yōu)先級等。重載運(yùn)算符時(shí),要注意該重載運(yùn)算符的運(yùn)算順序和優(yōu)先級不變,14,class A { public: A(int n) {

12、 //... } operator +(Aa,A&) { //... } operator *(Aa,AA) { //... } //... };,15,A a = 5,b = 6, c = 7,d= 8, e; e = a + b * c + d;//即

13、( a + (b * c ) ) + d 有了運(yùn)算符,編程就顯得方便。例如,對于直角三角形斜邊長度公式c= 用函數(shù)化的格式表示: c=sqrt(add(mult (a,a),mult(b,b) ) ); 用運(yùn)算符的格式表示: c=sqrt(a * a + b * b);,,,,,16,運(yùn)算符是函數(shù),除了運(yùn)算順序和優(yōu)先級不能更改外,參數(shù)和返回類型是可以重新說明的,即可以重載。重載的形式是:

14、 返回類型operator運(yùn)算符號(參數(shù)說明),17,例如:A類對象加法: class A{}; int operator +(A&,A&);//兩個(gè)A類對象參加運(yùn)算,返回int型值 C++規(guī)定,運(yùn)算符中,參數(shù)說明都是內(nèi)部類型時(shí),不能重載。例如不允許聲明: int* operator+(int,int*); 即不允許進(jìn)行下述運(yùn)算: int a=5; i

15、nt* pa=&a; pa=a*pa; //error C++基本數(shù)據(jù)類型之間的關(guān)系是確定的,如果允許定義其上的新操作 ,那么,基本數(shù)據(jù)類型的內(nèi)在關(guān)系將混亂。,18,C++還規(guī)定了“.、:: 、.* 、.->、?:”這五個(gè)運(yùn)算符不能重載,也不能創(chuàng)造新運(yùn)算符。 例如,不允許聲明: int operator @(int,int); 或者: int operator::(i

16、nt,int);,19,本章主要內(nèi)容,運(yùn)算符重載的需要性重載運(yùn)算符作友元函數(shù)運(yùn)算符作成員函數(shù)增量運(yùn)算符重載轉(zhuǎn)換運(yùn)算符重載賦值運(yùn)算符重載,,20,如果需要重載一個(gè)運(yùn)算符,使之能夠用于操作某類對象的私有成員,可以此將運(yùn)算符重載為該類的友元函數(shù)。重載為友元函數(shù)時(shí) 參數(shù)個(gè)數(shù)=原操作數(shù)個(gè)數(shù),且至少應(yīng)該有一個(gè)自定義類型的形參。友元函數(shù)是類以外的函數(shù),調(diào)用這種運(yùn)算符函數(shù)時(shí),所有的操作數(shù)都要通過參數(shù)傳遞來獲得。,運(yùn)算符友元函數(shù)的設(shè)計(jì)

17、,21,例一:,將+、-(雙目)重載為復(fù)數(shù)類的友元函數(shù)。 規(guī)則:實(shí)部和虛部分別相加減。兩個(gè)操作數(shù)都是復(fù)數(shù)類的對象。,#includeclass complex {public:complex(double r=0.0,double i=0.0) { real=r; imag=i; }friend complex operator + (complex c1,complex c2);

18、//運(yùn)算符+重載為友元函數(shù)friend complex operator - (complex c1,complex c2);//運(yùn)算符-重載為友元函數(shù)void display();//顯示復(fù)數(shù)的值private:double real;double imag;};,complex operator +(complex c1,complex c2)//運(yùn)算符重載友元函數(shù)實(shí)現(xiàn){ re

19、turn complex(c2.real+c1.real, c2.imag+c1.imag);}complex operator -(complex c1,complex c2)//運(yùn)算符重載友元函數(shù)實(shí)現(xiàn){return complex(c1.real-c2.real, c1.imag-c2.imag);}void complex::display(){cout<<&quo

20、t;real:"<<real<<" imag:"<<imag<<endl;},void main(){ complex c1(4.6,6.5), c2(3.9,1.4),c3,c4;c3=operator +(c1,c2); c3.display();//c3 = c1 + c2 ; // c3.display();},25,Vc6中 #

21、include "iostream"using namespace std; 會后fatal error C1001: INTERNAL 錯誤COMPILER ERROR用dev-c++能順利通過,例二:程序?qū)⑦\(yùn)算符+和++聲明為人民幣類的友元: class RMB{ public: RMB(unsigned int d,unsigned int c); friend

22、RMB operator + (RMB& ,RMB&); friend RMB& operator ++(RMB&); void display(){ cout <<(yuan + jf / 100.0) << endl; } private: unsigned int yuan; // 元 unsigned

23、int jf; // 角分};,RMB operator +(RMB& s1,RMB& s2){ unsigned int jf = s1.jf+s2.jf; unsigned int yuan = s1.yuan + s2.yuan ; RMB result(yuan,jf); return result;}RMB& operator ++(RMB&am

24、p; s){ s.jf ++; if(s.jf>=100){ s.jf-=100; s.yuan++; } return s;},28,RMB::RMB(unsigned int d, unsigned int c){ yuan = d; jf = c; while ( jf >=100 ){ //以使構(gòu)造時(shí),確保角分值小于100y

25、uan ++; jf -= 100; }},void main(){ RMB d1(2,48); RMB d2(3,28); RMB d3(0,0); d3 = d1 + d2; ++d3; d3.display(); },問題一: 為什么operator +( )中的參數(shù)用引用傳遞而不用指針傳遞?問題二: 為什么operator +( )由值返回

26、,而operator ++( )由引用返回?,30,operator+()和operator++()定義為友元是為了能訪問人民幣類的保護(hù)成員。 operator+()是一個(gè)雙目運(yùn)算符,它有兩個(gè)參數(shù)s1和s2,并且相加的結(jié)果仍為人民幣類,返回人民幣類對象。,31,注意:不是必須要讓operator+()執(zhí)行加法,可以讓它做任何事。但是不讓它做加法,而做其他操作是一個(gè)很糟的想法。如果重載+運(yùn)算符,向一個(gè)磁盤文件寫10次“I lik

27、e C++”,語法上可以,但與語義相差懸殊,不利于可讀性,背離了允許運(yùn)算符重載的初衷。當(dāng)別人讀這個(gè)程序時(shí),發(fā)現(xiàn)s1+s2的操作,想象是某種加法操作,怎么也想不到會是這樣的寫操作:所以在使重載運(yùn)算符脫離原義之前,必須保證有充分的理由。,32,->為什么operator+()中的參數(shù)用引用傳遞而不用指針傳遞? 因?yàn)橹羔槀鬟f存在程序上的可讀性問題:如果操作符重載聲明為: RMB operator+(RMB* a,RM

28、B* b); 則調(diào)用時(shí), RMB s1(5.1); RMB s2(6.7); RMB c=&sl+&s2;//是s1的地址與s2的地址相加嗎? operator++()是單目運(yùn)算符,它含有一個(gè)參數(shù)。operator++()對人民幣類對象的角分做加1運(yùn)算,如果它超過100,則對該對象的元做加1運(yùn)算并使角分為0(減100)。如果只給出一個(gè)operator++()定義,

29、那么它一般可用于前綴后綴兩種形式。即d3++與++d3不作區(qū)別。,33,值返回與引用返回,上節(jié)中,為什么operator+()由值返回,而operator++()由引用返回呢? 重載定義+和++操作的意義是人為的,所以返回類型并非一定如此規(guī)定。但如上節(jié)定義的+和++操作的意義,應(yīng)該規(guī)定+由值返回,++由引用返回。 對于operator+(),兩個(gè)對象相加,不改變其中任一個(gè)對象。而且它必須生成一個(gè)結(jié)果 對象來存放加法的結(jié)

30、果,并將該結(jié)果對象以值的方式返回給調(diào)用者。,34,如果+以引用返回如下例: RMB& operator +(RMB& s1,RMB& s2) { unsigned int jfs1.jf+s2.jf; unsigned int yuan=s1.yuan+s2.yuan; RMB result(yuan,Jf); return result;

31、 } 則盡管編譯正確,能夠運(yùn)行,但會產(chǎn)生奇怪的結(jié)果。例中的result對象由+運(yùn)算符函數(shù)的??臻g分配內(nèi)存,受限于塊作用域,引用返回導(dǎo)致了調(diào)用者使用這塊會被隨時(shí)分配的空間,35,能否將結(jié)果對象從堆中分配來避免上例的問題呢?例如:RMB& operator +(RMB& s1,RMB& s2){unsigned int jf=s1.jf+s2.jf;unsigned int yuan=s1.yua

32、n+s2.yuan;return *new RMB(yuan,jf);} 雖然它無編譯問題,可以運(yùn)行,但是該堆空間無法回收,因?yàn)闆]有指向該堆空間的指針,會導(dǎo)致內(nèi)存泄漏,程序不斷做加法時(shí),堆空間也在不斷流失。,36,如果堅(jiān)持結(jié)果對象從堆中分配,而返回一個(gè)指針,那樣在應(yīng)用程序中就要付出代價(jià):void fn(RMB& a,RMB& b) { RMB* pc=&(a+b);//c=a+b;

33、必須由此三條語句代替 RMB c= *pc; delete pc;} 通過值返回,將有一個(gè)臨時(shí)對象在調(diào)用者的棧空間產(chǎn)生,它復(fù)制被調(diào)函數(shù)的result對象,以便參加調(diào)用者中的表達(dá)式運(yùn)算,對于“c=a+b;”,則a+b的臨時(shí)對象賦給c,然后臨時(shí)對象的作用域也結(jié)束了。,37,與operator+()不一樣,operator++()確實(shí)修改了它的參數(shù),而且其返回值要求是左值,這個(gè)條件決定了它不能以值返回。如果以值返

34、回: RMB operator ++(RMB& s) {s.jf++; if(s.jf>-100) { s.jf-=100; s.yuan++; } return s; } RMB a(2,50); c= a++; //ok c= ++a; //ok,

35、a為2.52,38,本章主要內(nèi)容,運(yùn)算符重載的需要性重載運(yùn)算符作友元函數(shù)運(yùn)算符作成員函數(shù)增量運(yùn)算符重載轉(zhuǎn)換運(yùn)算符重載賦值運(yùn)算符重載New和delete運(yùn)算符重載,,重載為類成員函數(shù)時(shí) 參數(shù)個(gè)數(shù)=原操作數(shù)個(gè)數(shù)-1(后置++、--除外)作為成員的運(yùn)算符比之作為非成員的運(yùn)算符,在聲明和定義時(shí),形式上少一個(gè)參數(shù)。這是由于C++對所有的成員函數(shù)隱藏了第一個(gè)參數(shù)this。C++規(guī)定:=,(),[ ],->這4種運(yùn)算符必須

36、為成員函數(shù)。,40,例一:,將“+”、“-”運(yùn)算重載為復(fù)數(shù)類的成員函數(shù)。操作數(shù):兩個(gè)操作數(shù)都是復(fù)數(shù)類的對象。 一個(gè)運(yùn)算符除了可以作為一個(gè)非成員函數(shù)實(shí)現(xiàn)外,還可以作為一個(gè)成員函數(shù)實(shí)現(xiàn),#includeclass complex{public:complex(double r=0.0,double i=0.0){real=r;imag=i;}

37、 complex operator + (complex c2); //+重載為成員函數(shù)complex operator - (complex c2); //-重載為成員函數(shù)void display(); //輸出復(fù)數(shù)private:double real; //復(fù)數(shù)實(shí)部double imag; //復(fù)數(shù)虛部};,//

38、重載運(yùn)算符函數(shù)的實(shí)現(xiàn)complex complex::operator +(complex c2){complex c;c.real=c2.real+real;c.imag=c2.imag+imag;return complex(c.real,c.imag);},//重載運(yùn)算符 - 函數(shù)實(shí)現(xiàn)complex complex::operator - (complex c2){complex c;c.real

39、=real-c2.real;c.imag=imag-c2.imag;return complex(c.real,c.imag);},void complex::display(){ cout<<"("<<real<<","<<imag<<")"<<endl; }void main()

40、 //主函數(shù){complex c1(5,4),c2(2,10),c3; //定義復(fù)數(shù)類的對象cout<<"c1="; c1.display();cout<<"c2="; c2.display();c3=c1-c2;//使用重載運(yùn)算符完成復(fù)數(shù)減法cout<<"c3=c1-c2=";c3.display()

41、;c3=c1+c2;//使用重載運(yùn)算符完成復(fù)數(shù)加法cout<<"c3=c1+c2=";c3.display();},程序輸出的結(jié)果為:c1=(5,4)c2=(2,10)c3=c1-c2=(3,-6)c3=c1+c2=(7,14),例二:class RMB{ public: RMB(unsigned int d,unsigned int c);

42、 RMB operator + (RMB& ); RMB operator+(int); RMB& operator ++(); void display(){ cout << (yuan + jf / 100.0) << endl; } private: unsigned int yuan; // 元 unsi

43、gned int jf; // 角分};,RMB RMB::operator +(RMB& s){ unsigned int c= jf+s.jf; unsigned int d = yuan + s.yuan ; RMB result(d , c); return result;}RMB& RMB::operator ++(){ jf ++;

44、 if(jf>=100){ jf-=100; yuan++; } return *this;},48,RMB RMB::operator +(int c){ RMB result(5,c); return result;}RMB::RMB(unsigned int d, unsigned int c){ yuan = d; jf = c;

45、while(jf >=100){ yuan ++; jf -= 100;}},void main(){ RMB d1(2,48); RMB d2(3,28); RMB d3(0,0); d3 = d1 + d2; // d3 = d1 +2; //d3 = 2 +d1;//error//d3=d1.operator +(d2); ++d3;/

46、/d3.operator ++(); d3.display(); },問題:成員和友元運(yùn)算符函數(shù)有區(qū)別嗎?,50,,從中看出,作為成員的運(yùn)算符比之作為非成員的運(yùn)算符,在聲明和定義時(shí),形式上少一個(gè)參數(shù)。這是由于C++對所有的成員函數(shù)隱藏了第一個(gè)參數(shù)this,51,RMB operator +(RMB& s1,RMB& s2) //非成員形式{ unsigned int jf:s.jf+s2.

47、jf; unsigned int yuan s1.yuan+s2.yuan; RMB result(yuan,jf); return result; }RMB RMB::operator +(RMB& s) //成員形式 { unsigned int c=jf+s.jf; unsigned int d=yuan

48、+s.yuan; RMB result(c,d); return result;},52,可見函數(shù)體中內(nèi)容幾乎相同,只是非成員形式加s1和s2,成員形式s加當(dāng)前對象,當(dāng)前對象的成員隱含著由this指向。即yuan意味著this—>yuan。 一個(gè)運(yùn)算符成員形式,將比非成員形式少一個(gè)參數(shù),左邊參數(shù)是隱含的。 作為人民幣類的一種常規(guī)操作,我們應(yīng)該允許其中有一個(gè)操作數(shù)是double型的情況:

49、 c=c+2.5; c=2.7+c;,53,RMB d3(0, 0);//d3=d1.operator +(d2); d3 = d1 +2;RMB RMB::operator +(int c){ RMB result(5,c); return result;},54,但是由于參數(shù)類型不同,上例的運(yùn)算符不論是成員形式還是非成員形式,都不能被這兩個(gè)調(diào)用所匹配,還必須重載下列兩個(gè)成員運(yùn)算符:

50、RMB operator +(RMB& s,double d) { unsigned int y=s.yuan+d; unsigned int j=s.jf+(d-(int)d)* 100+0.5; RMB result(y,j); } inline RMB operator +(double d,RMB& s) { return

51、s+d;} 這里第二個(gè)重載運(yùn)算符調(diào)用了第一個(gè)重載運(yùn)算符,兩者之間只是參數(shù)順序相反,定義后者為內(nèi)聯(lián)函數(shù)是一個(gè)技巧,省去了必要的開銷。,55,從中得出,為了適應(yīng)其中一個(gè)操作數(shù)是double的情況,不得不額外引入兩個(gè)重載運(yùn)算符。如果有構(gòu)造函數(shù): RMB(double value) { yuan=value; jf=(value-yuan)*100.0+0.5; } 就

52、能夠?qū)ouble通過構(gòu)造,變換成RMB類,于是: , class RMB { public: RMB(unsigned int d,unsigned int c); RMB(double value); friend RMB operator +(RMB& sl, RMB& s2); //其余同前 };,56,v

53、oid main(){ RMB s(5.8); s=RMB(1.5)+s;//顯式轉(zhuǎn)換(創(chuàng)建——個(gè)無名對象) s=1.5+s;//隱式轉(zhuǎn)換 s=s+1.5; //隱式轉(zhuǎn)換 s=s+1;//將in仁變換成double,然后像上面那樣變換 } 現(xiàn)在不必定義operator +(double,RMB&)和operator +(RMB&,double)了,

54、因?yàn)榭蓪ouble轉(zhuǎn)換成RMB類,然后匹配operator +(RMB&,RMB&),57,該變換可以是顯式的,如s=RMB(1.5)+s那樣,也可以是隱含的。此時(shí),由于其中的一個(gè)操作數(shù)是RMB對象,而且參數(shù)個(gè)數(shù)相同,所以它首先假定operator +(RMB&,RMB&)可以匹配,然后尋找能夠使用的轉(zhuǎn)換。發(fā)現(xiàn)構(gòu)造函數(shù)RMB(double)可作為轉(zhuǎn)換的依據(jù)。在完成轉(zhuǎn)換后,真正匹配operator +(R

55、MB&,RMB&)運(yùn)算符。所以程序員可以通過定義轉(zhuǎn)換函數(shù),來減少定義的運(yùn)算符個(gè)數(shù)。 但是如果是下面的情況: s=1.5+6.4;那么由于左右操作數(shù)都是double型,所以匹配基本數(shù)據(jù)類型的加法,進(jìn)行浮點(diǎn)運(yùn)算。然后因?yàn)橘x值表達(dá)式左面是RMB對象,所以該賦值運(yùn)算將右面表達(dá)式的結(jié)果用構(gòu)造函數(shù)RMB(double)進(jìn)行RMB轉(zhuǎn)換,再賦值給s。C++規(guī)定:=,(),[],—>這四種運(yùn)算符必須為成員形式。

56、,58,在實(shí)現(xiàn)加法運(yùn)算符時(shí),用的是非成員形式。如果將運(yùn)算符改成成員形式,那么,對于s=1.5+s;的形式,仍然必須要有重載運(yùn)算符RMB operator +(double,RMB&)來支持,因?yàn)樵诒磉_(dá)式1.5+s中,左面的1.5不能匹配RMB::operator+(RMB&)中的隱含類對象,由于沒有雙目運(yùn)算符的非成員形式,所以也無法利用類的轉(zhuǎn)換來創(chuàng)造匹配的條件。這就是為什么有些運(yùn)算符重載(如復(fù)數(shù)類的+、—運(yùn)算)用非成員形

57、式的原因。,59,本章主要內(nèi)容,運(yùn)算符重載的需要性重載運(yùn)算符作友元函數(shù)運(yùn)算符作成員函數(shù)增量運(yùn)算符重載轉(zhuǎn)換運(yùn)算符重載賦值運(yùn)算符重載,,前增量與后增量的區(qū)別-- 使用前增量時(shí),對對象(操作數(shù))進(jìn)行增量修改,然后再返回該對象。所以前增量運(yùn)算符 操作時(shí),參數(shù)與返回的是同一個(gè)對象:這與基本數(shù)據(jù)類型的前增量操作類似,返回的也是左 值。-- 使用后增量時(shí),必須在增量之前返回原有的對象值。為此,需要創(chuàng)建一個(gè)臨時(shí)對象,存 放原有的對象,

58、以便對操作數(shù)(對象)進(jìn)行增量修改時(shí),保存最初的值。后增量操作返回的是 原有對象值,不是原有對象,原有對象已經(jīng)被增量修改,所以,返回的應(yīng)該是存放原有對象值的臨時(shí)對象。,C++約定,在增量運(yùn)算符定義中,放上一個(gè)整數(shù)形參,就是后增量運(yùn)算符 class Increase{public:Increase(int x) : value(x){ }Increase& operator ++(); // 前增量Incr

59、ease operator ++(int); // 后增量void display(){cout<<"the value is"<<value<<endl;}private:int value;};,Increase& Increase::operator ++(){value++; //先增量 return *this; //再返回原

60、對象 }Increase Increase::operator ++(int){Increase temp(*this); //臨時(shí)對象存放原有對象值 value++; //原有對象增量修改 return temp; //返回原有對象值 },void main(){Increase n(20); n.display();(n++).display(); //顯示臨時(shí)對象值 n.display();

61、 //顯示原有對象 (++n).display();++(++n);n.display();(n++)++; //第二次增量操作對臨時(shí)對象進(jìn)行 n.display();},64,運(yùn)行結(jié)果為 the value is 20 the value iS 20 the value iS 21 the value is 22 the value is 24 t

62、he value is 25 前后增量操作的意義,決定了其不同的返回方式。前增量運(yùn)算符返回引用,后增量運(yùn)算符返回值。 后增量運(yùn)算符中的參數(shù)int只是為了區(qū)別前增量與后增量,除此之外沒有任何作用。因 為定義中,無須使用該參數(shù),所以形參名在定義頭中省略。對于(n++)++中的第二個(gè)++是對返回的臨時(shí)對象所作的,從最后一行輸出可以看出 對n的修改只發(fā)生一次。,65,class A{public: A(int

63、w) { age=w; }A ff(){A aa(*this);//臨時(shí)對象存放原有對象值 return aa; }int age; };void main(){ A a1(34); A a2=a1.ff(); cout<<a2.age<<endl;},66,非成員形式重載,前增量和后增量的非成員運(yùn)算符,也有類似的編譯區(qū)分方法。例如,下

64、面的程序?qū)?前增量和后增量運(yùn)算符修改為非成員形式:,67,class Increase{public: Increase(int x):value(x){} friend Increase & operator ++(Increase & ); //前增量 friend Increase operator ++ (Increase & int); //后增量 void di

65、splay(){ cout <<"the value is " <<value <<endl; }private: int value;};,68,Increase & operator ++(Increase & a){ a.value++; //前增量 return a;

66、 //再返回原對象}Increase operator ++ (Increase& a, int){ Increase temp(a); //通過拷貝構(gòu)造函數(shù)保存原有對象值 a.value++; //原有對象增量修改 return temp; //返回原有對象值},69,void ma

67、in(){ Increase n(20); n.display(); (n++).display(); //顯示臨時(shí)對象值 n.display(); //顯示原有對象 ++n; n.display(); ++(++n); n.display(); (n++)++; //第二次增

68、量操作對臨時(shí)對象進(jìn)行 n.display(); cin.get();},70,運(yùn)行結(jié)果為: the value iS 20 the value iS 20 the value iS 21 the value is 22 the value iS 24 the value iS 25 可見,前增量和后增量運(yùn)算符的定義以及成員形式與非成員形式稍有不同

69、,但前增量和后增量運(yùn)算符的使用完全相同。,71,本章主要內(nèi)容,運(yùn)算符重載的需要性重載運(yùn)算符作友元函數(shù)運(yùn)算符作成員函數(shù)增量運(yùn)算符重載轉(zhuǎn)換運(yùn)算符重載賦值運(yùn)算符重載,,程序中在進(jìn)行賦值、計(jì)算、給函數(shù)傳值以及從函數(shù)返回值時(shí),經(jīng)常會發(fā)生類型之間的轉(zhuǎn)換。怎樣轉(zhuǎn)換用戶自定義類型呢?通過轉(zhuǎn)換構(gòu)造函數(shù)能把其他類型(包括內(nèi)部類型)的對象轉(zhuǎn)換為某個(gè)特定類型的對象。轉(zhuǎn)換運(yùn)算符可以把一種類的對象轉(zhuǎn)換為其它類的對象或內(nèi)部類型的值。,轉(zhuǎn)換運(yùn)算符只能

70、是一個(gè)非靜態(tài)的成員函數(shù),而不能是友元函數(shù)。在類定義體中聲明形式: operator 類型名();它沒有返回類型,因?yàn)轭愋兔痛砹怂姆祷仡愋?,故返回類型顯得多余。轉(zhuǎn)換運(yùn)算符將對象轉(zhuǎn)換成類型名規(guī)定的類型。轉(zhuǎn)換時(shí)的形式就像強(qiáng)制轉(zhuǎn)換一樣 如果 沒有轉(zhuǎn)換運(yùn)算符定義,直接用強(qiáng)制轉(zhuǎn)換是不行的,因?yàn)閺?qiáng)制轉(zhuǎn)換只能對基本數(shù)據(jù)類型進(jìn)行操 作,對類類型的操作是沒有定義的。,74,,定義函數(shù)體:類名::operate type(){

71、 // … return type類型的對象},下面的程序在類中定義了轉(zhuǎn)換運(yùn)算符,在主函數(shù)中將double數(shù)分別顯式和隱式轉(zhuǎn)換成RMB對象:class RMB{ public: RMB(double value=0.0);operator double(){return yuan+jf/100.0;}void display(){cout<<(yua

溫馨提示

  • 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. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論