《c++程序設(shè)計》課件第7章 運算符重載_第1頁
《c++程序設(shè)計》課件第7章 運算符重載_第2頁
《c++程序設(shè)計》課件第7章 運算符重載_第3頁
《c++程序設(shè)計》課件第7章 運算符重載_第4頁
《c++程序設(shè)計》課件第7章 運算符重載_第5頁
已閱讀5頁,還剩104頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第7章運算符重載2第7章運算符重載本章學(xué)習(xí)要點為什么要進(jìn)行運算符重載運算符重載的方法重載運算符的規(guī)則運算符重載函數(shù)作為類成員函數(shù)和友元函數(shù)重載雙目運算符重載單目運算符重載流插入運算符和流提取運算符不同類型數(shù)據(jù)間的轉(zhuǎn)換3第7章運算符重載函數(shù)重載,就是賦給同一個函數(shù)名多個含義。運算符重載是指同一個運算符可以施加于不同類型的操作數(shù)上面。4classMoney{public:Money(inty=0,intj=0,intf=0){yuan=y;jiao=j;fen=f;optimize();}voidDisplay(string);private:intyuan,jiao,fen;voidOptimize();//優(yōu)化函數(shù)};voidMoney::Optimize(){if(fen>=10){jiao++;fen-=10;}if(jiao>=10){yuan++;jiao-=10;}}voidMoney::Display(stringstr){cout<<str<<"="<<yuan<<"."<<jiao<<fen<<"¥"<<endl;}Moneycost1(10,3,5);Moneycost2(5,8,2),total;total=cost1+cost2;構(gòu)造函數(shù)5classMoney{public:Money(inty=0,intj=0,intf=0){yuan=y;jiao=j;fen=f;optimize();}voidDisplay(string);

friend

MoneyMoneyAdd(Money&c1,Money&c2);private:intyuan,jiao,fen;voidOptimize();};voidMoney::Optimize(){if(fen>=10){jiao++;fen-=10;}if(jiao>=10){yuan++;jiao-=10;}}voidMoney::Display(stringstr){cout<<str<<"="<<yuan<<"."<<jiao<<fen<<"¥"<<endl;}MoneyMoneyAdd(Money&c1,Money&c2){

returnMoney(c1.yuan+c2.yuan,c1.jiao+c2.jiao,c1.fen+c2.fen);}intmain(){Moneycost1(300,5,6),cost2(105,7,6),total1;total1=MonetAdd(cost1,cost2);total1.Display("total1=cost1+cost2");return0;}6classMoney{public:Money(inty=0,intj=0,intf=0){yuan=y;jiao=j;fen=f;optimize();}voidDisplay(string);MoneyMoneyAdd(Money&c2);private:intyuan,jiao,fen;voidOptimize();};voidMoney::Optimize(){if(fen>=10){jiao++;fen-=10;}if(jiao>=10){yuan++;jiao-=10;}}voidMoney::Display(stringstr){cout<<str<<"="<<yuan<<"."<<jiao<<fen<<"¥"<<endl;}MoneyMoney::MoneyAdd(Money&c2){returnMoney(yuan+c2.yuan,jiao+c2.jiao,fen+c2.fen);}intmain(){Moneycost1(300,5,6),cost2(105,7,6),total1;total1=cost1.MonetAdd(cost2);total1.Display("total1=cost1+cost2");return0;}77.1為什么要進(jìn)行運算符重載但我們希望在程序中直接用運算符“+”對Money類的對象進(jìn)行相加運算。

total1=cost1+cost2;對運算符“+”進(jìn)行重載以后,就可以這樣書寫了。87.1為什么要進(jìn)行運算符重載有了針對自定義類型數(shù)據(jù)的運算符重載,不僅使我們編程時感到十分方便,而且寫出的表達(dá)式與數(shù)學(xué)表達(dá)式很相似,符合人們的習(xí)慣。97.2運算符重載的方法重載運算符的函數(shù)的一般格式如下:函數(shù)類型operator運算符名稱(形參列表){對運算符的重載處理}函數(shù)名函數(shù)名是由operator和運算符組成,如operator+意思是對運算符“+”重載。重載運算符的函數(shù)可以是類的成員函數(shù),也可以是類的友元函數(shù),還可以是既非類的成員函數(shù)也非類的友元函數(shù)的普通函數(shù)10【例7-1】對“+”運算符進(jìn)行重載來實現(xiàn)兩個Money類對象的加法運算。7.2運算符重載的方法11#include<iostream>#include<string>usingnamespacestd;classMoney{public:Money(inty=0,intj=0,intf=0);Moneyoperator+(Money&);voidDisplay(string);private:intyuan,jiao,fen;voidOptimize();};voidMoney::Optimize(){if(fen>=10){jiao++;fen-=10;}if(jiao>=10){yuan++;jiao-=10;}}Money::Money(inty,intj,intf){yuan=y;jiao=j;fen=f;Optimize();}MoneyMoney::operator+(Money&c2){returnMoney(yuan+c2.yuan,jiao+c2.jiao,fen+c2.fen);}voidMoney::Display(stringstr){cout<<str<<"="<<yuan<<"."<<jiao<<fen<<"¥"<<endl;}函數(shù)名intmain(){Moneycost1(300,5,6),cost2(105,7,6),total1,total2;total1=cost1+cost2;total2=cost1.operator+(cost2);total1.Display("total1=cost1+cost2");total2.Display("total2=cost1+cost2");return0;}12運算符重載函數(shù)可以是:⑴類的成員函數(shù)

可以通過this指針自由地訪問本類的數(shù)據(jù)成員,少寫一個函數(shù)參數(shù)。7.2運算符重載的方法成員函數(shù)定義:MoneyMoney::operator+(Money&c2){returnMoney(yuan+c2.yuan,jiao+c2.jiao,fen+c2.fen);}ComplexComplex::operator+(Complex&c2){returnComplex(real+c2.real,imag+c2.imag);}調(diào)用:

total1=cost1+cost2;表達(dá)式cost1+cost2中第一個參數(shù)cost1是Money類對象,運算符函數(shù)返回值的類型也是Money,這是正確的。如果cost1不是Money類的對象,它就無法通過隱式this指針訪問Money類的成員了。如果函數(shù)返回值不是Money類復(fù)數(shù),顯然這種運算是沒有實際意義的。7.2運算符重載的方法14⑵類的友元函數(shù)雙目運算符重載為友元函數(shù)時,在函數(shù)的形參表列中必須有兩個參數(shù)。聲明:friendMoneyoperator+(Money&c1,Money&c2);友元函數(shù)定義:Moneyoperator+(Money&c1,Money&c2){returnComplex(c1.yuan+c2.yuan,c1.jiao+c2.jiao,c1.fen+c2.fen);}調(diào)用:total1=cost1+cost2;形參的順序任意,不要求第一個參數(shù)必須為類對象。要求運算符左側(cè)的操作數(shù)與第一個參數(shù)對應(yīng),運算符右側(cè)的操作數(shù)與第二個參數(shù)對應(yīng)。7.2運算符重載的方法157.3重載運算符的規(guī)則(1)C++不允許用戶自己定義新的運算符,只能對C++語言中已有的運算符進(jìn)行重載。例如,雖然在某些程序設(shè)計語言中用雙字符“**”作為求冪運算符,但是在使用C++進(jìn)行程序設(shè)計時,不能將“**”作為運算符進(jìn)行重載,因為“**”不是C++語言的合法運算符。(2)運算符重載針對新類型數(shù)據(jù)的實際需要,對原有運算符進(jìn)行適當(dāng)?shù)母脑?。一般來講,重載的功能應(yīng)當(dāng)與原有功能相類似。7.3重載運算符的規(guī)則(3)C++允許重載的運算符包括C++中幾乎所有的運算符。具體規(guī)定如表7-1所示。表7-1C++允許重載的運算符運算符名稱具體運算符算術(shù)運算符+(加),-(減),*(乘),/(除),%(取模),++(自增),--(自減)位操作運算符&(按位與),~(按位取反),^(按位異或),|(按位或),<<(左移),>>(右移)邏輯運算符!(邏輯非),&&(邏輯與),||(邏輯或)比較運算符<(小于),>(大于),>=(大于等于),<=(小于等于),==(等于),!=(不等于)賦值運算符=,+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=其他運算符[](下標(biāo)),()(函數(shù)調(diào)用),->(成員訪問),,(逗號),new,delete,new[],delete[],->*(成員指針訪問)177.3重載運算符的規(guī)則運算符功能.成員訪問運算符.*成員指針訪問運算符::域運算符sizeof長度運算符?:條件運算符表7-2C++不允許重載的運算符187.3重載運算符的規(guī)則(4)堅持4個“不能改變”。即不能改變運算符操作數(shù)的個數(shù);不能改變運算符原有的優(yōu)先級;不能改變運算符原有的結(jié)合性;不能改變運算符原有的語法結(jié)構(gòu)。單目運算符重載后只能是單目運算符,雙目運算符重載后依然是雙目運算符。C++語言已經(jīng)預(yù)先規(guī)定了每個運算符的優(yōu)先級,以決定運算次序。不論怎么進(jìn)行重載,各運算符之間的優(yōu)先級別不會改變。C++語言已經(jīng)預(yù)先規(guī)定了每個運算符的結(jié)合性。197.3重載運算符的規(guī)則(5)重載的運算符必須和用戶定義的自定義類型對象一起使用,其參數(shù)至少應(yīng)有一個是類對象(或類對象的引用)。也就是說,參數(shù)不能全部是C++的標(biāo)準(zhǔn)類型,以防止用戶修改用于標(biāo)準(zhǔn)類型數(shù)據(jù)的運算符的性質(zhì)。如果有兩個參數(shù),可以都是類對象,也可以一個是類對象,一個是C++標(biāo)準(zhǔn)類型的數(shù)據(jù):Moneyoperator+(inta,Moneyc){return(Money(c.yuan,c.jiao,

a+c.fen);}防止用戶:intoperator+(inta,intb){return(a-b);}207.3重載運算符的規(guī)則(6)重載運算符的函數(shù)不能有默認(rèn)的參數(shù),否則就改變了運算符參數(shù)的個數(shù)。(7)用于類對象的運算符一般必須重載,但有兩個例外,運算符“=”和“&”可以不必用戶重載。①賦值運算符(=)可以用于每一個類對象,可以利用它在同類對象之間相互賦值。②地址運算符&也不必重載,它能返回類對象在內(nèi)存中的起始地址。217.3重載運算符的規(guī)則注意:(1)考慮到各種因素,雙目運算符一般重載為類的友元函數(shù),單目運算符一般重載為類的成元函數(shù)。(2)C++規(guī)定,=,(),[],->必須重載為類的成員函數(shù),<<,>>必須重載為類的友元函數(shù)。227.4運算符重載函數(shù)作為類的成員函數(shù)和友元函數(shù)7.4.1運算符重載函數(shù)作為類的成員函數(shù)7.4.2運算符重載函數(shù)作為類的友元函數(shù)237.4.1運算符重載函數(shù)作為類的成員函數(shù)將運算符重載函數(shù)定義為類的成員函數(shù)的原型在類的內(nèi)部聲明格式如下:class類名{

…返回類型operator運算符(形參表);

…};在類外定義運算符重載函數(shù)的格式如下:返回類型類名::operator運算符(形參表){函數(shù)體}24【例7-2】通過運算符重載為類的成員函數(shù)來實現(xiàn)兩個有理數(shù)對象的加、減、乘和除運算。#include<math.h>#include<iostream>usingnamespacestd;classrational//聲明有理數(shù)類{public:rational(intx=0,inty=1);//構(gòu)造函數(shù)

voidprint();rationaloperator+(rationala);//重載運算符"+"

rational

operator-(rationala);//重載運算符"-"private:intnum,den;voidoptimi();};//優(yōu)化有理數(shù)函數(shù)25voidrational::optimi()//定義有理數(shù)優(yōu)化函數(shù){intgcd;

if(num==0)//若分子為0,則置分母為1后返回

{den=1;return;}gcd=(abs(num)>abs(den)?abs(den):abs(num));if(gcd==0)return;//若為0,則返回

for(inti=gcd;i>1;i--)//用循環(huán)找最大公約數(shù)

if((num%i==0)&&(den%i==0))break;num/=i;//i為最大公約數(shù),將分子、分母均整除它,重新賦值

den/=i;

//若分子和分母均為負(fù)數(shù),則結(jié)果為正,所以均改為正

if(num<0&&den<0){num=-num;den=-den;}elseif(num<0||den<0)

{//若分子和分母中只有一個為負(fù)數(shù),則調(diào)整為分子取負(fù),分母取正

num=-abs(num);den=abs(den);}}26voidrational::print()//輸出有理數(shù){cout<<num;

//當(dāng)分子不為0且分母不為1時才顯示"/分母“

if(num!=0&&den!=1)cout<<"/"<<den<<"\n";elsecout<<"\n";}7.4.1運算符重載函數(shù)作為類的成員函數(shù)27rationalrational::operator+(rationala){//“+”運算符重載函數(shù),根據(jù)前面所列的算法寫出表達(dá)式

rationalr;r.den=a.den*den;

r.num=a.num*den+a.den*num;

r.optimi();returnr;}rationalrational::operator-(rationala){//“-”運算符重載函數(shù),根據(jù)前面所列的算法寫出表達(dá)式

rationalr;r.den=a.den*den;

r.num=num*a.den-den*a.num;

r.optimi();returnr;}28intmain(){rationalr1(3,14),r2(4,14),r3,r4;r1.print();r2.print();r3=r1+r2;//使用重載了的運算符“+”r3.print();r4=r1-r2;//使用重載了的運算符“-”r4.print();return0;}7.4.1運算符重載函數(shù)作為類的成員函數(shù)297.4.2運算符重載函數(shù)作為類的友元函數(shù)將運算符重載函數(shù)定義為類的友元函數(shù),其原型在類的內(nèi)部聲明格式如下:class類名{

friend返回類型operator運算符(形參表);

…};在類外定義友元運算符重載函數(shù)的格式如下:返回類型operator運算符(形參表){函數(shù)體}30【例7-3】將運算符“+”和“-”重載為適合于有理數(shù)加減法,重載函數(shù)不作為成員函數(shù),而放在類外,作為rational類的友元函數(shù)。#include<math.h>#include<iostream.h>classrational//聲明有理數(shù)類{public:

//重載函數(shù)作為友元函數(shù)friend

rational

operator+(rationala,rationalb);//重載函數(shù)作為友元函數(shù)friend

rational

operator-(rationala,rationalb);private:…};31//定義作為友元函數(shù)的重載函數(shù)rational

operator+(rationala,rationalb){rationalr;r.den=a.den*b.den;r.num=a.num*b.den+a.den*b.num;r.optimi();returnr;}//定義作為友元函數(shù)的重載函數(shù)rationaloperator-(rationala,rationalb){rationalr;r.den=a.den*b.den;r.num=a.num*b.den-a.den*b.num;r.optimi();returnr;}32intmain(){rationalr1(3,14),r2(4,14),r3,r4;r1.print();r2.print();r3=r1+r2;//使用重載了的運算符“+”

r3.print();

r4=r1-r2;

//使用重載了的運算符“-”

r4.print();return0;}7.4.2運算符重載函數(shù)作為類的友元函數(shù)337.5重載雙目運算符雙目運算符(或稱二元運算符)有兩個操作數(shù),通常在運算符的左右兩側(cè),如x+y,t=3,a<=b等。由于雙目運算符有兩個操作符,因此:

如果運算符重載函數(shù)為友元函數(shù),則有兩個參數(shù)。

如果運算符重載函數(shù)為成員函數(shù),則可以省略一個參數(shù)。345.2向上類型轉(zhuǎn)換【例7-4】定義一個Time類,用來存放做某件事所花費的時間,如3小時15分鐘,分別重載運算符“+”用于求兩段時間的和,重載運算符“-”用于求兩段時間的差。#include<iostream.h>

classTime{

public:

Time();Time(inth,intm=0);friendTimeoperator+(Time&t1,Time&t2);friendTimeoperator-(Time&t1,Time&t2);voidShow();private:inthours,minutes;};Time::Time(){hours=minutes=0;}Time::Time(inth,intm){hours=h;minutes=m;}355.2向上類型轉(zhuǎn)換voidTime::Show(){cout<<hours<<"hours,"<<minutes<<"minutes";}Timeoperator+(Time&t1,Time&t2){Timesum;sum.minutes=t1.minutes+t2.minutes;sum.hours=t1.hours+t2.hours+sum.minutes/60;sum.minutes%=60;returnsum;}Timeoperator-(Time&t1,Time&t2){Timedif;intx1,x2;

x1=t2.hours*60+t2.minutes;x2=t1.hours*60+t1.minutes;dif.minutes=(x2-x1)%60;dif.hours=(x2-x1)/60;returndif;}365.2向上類型轉(zhuǎn)換intmain(){

Timet1(5,30),t2(2,48),t3,t4;cout<<"t1=";t1.Show();cout<<endl;cout<<"t2=";t2.Show();cout<<endl;cout<<"t3=t1+t2=";t3=t1+t2;t3.Show();cout<<endl;cout<<"t4=t1-t2=";t4=t1-t2;t4.Show();cout<<endl;

return0;}37指針懸掛【例3-19】默認(rèn)賦值運算符重載函數(shù)引起的指針懸掛問題?!纠?-5】重載賦值運算符函數(shù)解決指針懸掛問題。#include<string>#include<cassert>classString//自定義字符串類{public:

String();//默認(rèn)構(gòu)造函數(shù)

String(constchar*src);//帶參數(shù)的構(gòu)造函數(shù)~String();//析構(gòu)函數(shù)constchar*ToString()const{returnstr;}

unsignedintLength()const{returnlen;}String&operator=(constString&right);private:

char*str;

unsignedintlen;};String::String()//默認(rèn)構(gòu)造函數(shù){len=0;str=newchar[len+1];

str[0]='\0';}String::String(constchar*src)//帶參數(shù)的構(gòu)造函數(shù){len=strlen(src);str=newchar[len+1];if(!str){cerr<<"AllocationError!\n";exit(1);}strcpy(str,src);}String::~String()//析構(gòu)函數(shù){deletestr;str=NULL;}String&String::operator=(constString&right){if(&right!=this){intlength=right.Length();if(len<length) {delete[]str;str=newchar[length+1];assert(str!=0); }for(inti=0;right.str[i]!='\0';i++)str[i]=right.str[i];str[i]='\0';len=length; } return*this;}指針懸掛intmain(){ Stringstr1("Hi!"),str2("Hello!"); cout<<"str1:"<<str1.ToString()<<endl;cout<<"str2:"<<str2.ToString()<<endl; str1=str2;cout<<"str1:"<<str1.ToString()<<endl; return0;}427.6重載單目運算符單目運算符只有一個操作數(shù),如!a,-b,&c,*p,--i,++i等。由于單目運算符只有一個操作符,因此:

如果運算符重載函數(shù)為友元函數(shù),則只能有一個參數(shù)。

如果運算符重載函數(shù)為成員函數(shù),則可以省略此參數(shù)。435.2向上類型轉(zhuǎn)換【例7-6】設(shè)計一個Point類,有私有數(shù)據(jù)成員x和y表示屏幕上的一個點的水平和垂直兩個方向的坐標(biāo)值,分別實現(xiàn)對自增“++”和自減“--”運算符的重載。#include<iostream>usingnamespacestd;

classPoint{public:Point();

Point(intvx,intvy);

Pointoperator++();//前置自增Pointoperator--();//前置自減

voiddisplay();private:

intx,y;};445.2向上類型轉(zhuǎn)換Point::Point(){

x=0;

y=0;}Point::Point(intvx,intvy){

x=vx;

y=vy;}voidPoint::display(){

cout<<"("<<x<<","<<y<<")"<<endl;

}PointPoint::operator++();//前置自增{if(x<640)x++;//不超過屏幕的橫界if(y<480)y++;//不超過屏幕的豎界

return*this;}

PointPoint::operator--();//前置自減{

if(x>0)x--;if(y>0)y--;

return*this;}455.2向上類型轉(zhuǎn)換intmain(){Pointp1(10,10),p2(150,150);

cout<<"p1=";p1.display();

++p1;//測試前置自增

cout<<"++p1=";

p1.display();

cout<<"p2=";p2.display();

--p2;//測試前置自減

cout<<"-p2=";

p2.display();return0;}467.6重載單目運算符在C++中,前置單目運算符和后置單目運算符重載的主要區(qū)別就在于重載函數(shù)的形參。語法規(guī)定:(1)前置單目運算符重載為類的成員函數(shù)時沒有形參,而后置單目運算符重載為類的成員函數(shù)時需要有一個int型形參。這個int型的參數(shù)在函數(shù)體內(nèi)并不使用,純粹是用來區(qū)別前置與后置,因此參數(shù)表中可以只給出類型名,沒有參數(shù)名。(2)前置單目運算符重載為類的友元函數(shù)時有一個形參,即為類的對象,而后置單目運算符重載為類的友元函數(shù)時需要有兩個參數(shù),一個是類的對象,一個是int型形參。47【例7-7】在【例7-6】的基礎(chǔ)上,增加后置單目運算符“++”和“--”的重載,其中將前置和后置的“++”運算均重載為類的成員函數(shù),將前置和后置的“--”運算均重載為類的友元函數(shù)。7.6重載單目運算符48#include<iostream>usingnamespacestd;

classPoint{public:Point();

Point(intvx,intvy);

Pointoperator++();//重載前置自增為類的成員函數(shù)Pointoperator++(int);//重載后置自增為類的成員函數(shù)

//重載前置自減為類的友元函數(shù)friendPointoperator--(Point&p1);

//重載后置自減為類的友元函數(shù)friendPointoperator--(Point&p1,int);

voiddisplay();private:intx,y;};49Point::Point(){

x=0;

y=0;}Point::Point(intvx,intvy){

x=vx;

y=vy;}voidPoint::display(){cout<<"("<<x<<","<<y<<")"<<endl;

}PointPoint::operator++()//前置自增{if(x<640)x++;//不超過屏幕的橫界if(y<480)y++;//不超過屏幕的豎界

return*this;}PointPoint::operator++(int)//后置自增{//先將當(dāng)前對象通過復(fù)制構(gòu)造函數(shù)臨時保存起來

Pointtemp(*this);if(x<640)x++;//不超過屏幕的橫界if(y<480)y++;//不超過屏幕的豎界

returntemp;}505.2向上類型轉(zhuǎn)換

Pointoperator--(Point&p1)//前置自減{

if(p1.x>0)p1.x--;if(p1.y>0)p1.y--;

returnp1;}Pointoperator--(Point&p1,int)//后置自減{//先將當(dāng)前對象通過復(fù)制構(gòu)造函數(shù)臨時保存起來Pointtemp(p1);if(p1.x>0)p1.x--;if(p1.y>0)p1.y--;returntemp;}515.2向上類型轉(zhuǎn)換intmain(){Pointp1(10,10),p2(150,150),p3(20,20),p4(160,160),p5;cout<<"p1=";p1.display();++p1;//測試前置自增

cout<<"++p1=";

p1.display();cout<<"p3=";p3.display();p5=p3++;//測試后置自增

cout<<"p3++=";

p3.display();cout<<"p5=p3++=";p5.display();

cout<<"p2=";p2.display();--p2;//測試前置自減

cout<<"--p2=";p2.display();cout<<"p4=";p4.display();

p5=p4--;//測試后置自增

cout<<"p4--=";

p4.display();cout<<"p5=p4--=";

p5.display();return0;}527.7重載流插入運算符和流提取運算符在類庫提供的頭文件中已經(jīng)對“<<”和“>>”進(jìn)行了重載,使之作為流插入運算符和流提取運算符,能用來輸出和輸入C++標(biāo)準(zhǔn)類型的數(shù)據(jù)。用戶自己定義的類型的數(shù)據(jù),是不能直接用“<<”和“>>”來輸出和輸入的。如果想用它們輸出和輸入自己定義的類型的數(shù)據(jù),就必須對它們進(jìn)行重載。537.7重載流插入運算符和流提取運算符對“<<”和“>>”重載的函數(shù)形式如下:ostream&

operateor<<(ostream&,自定義類);istream&

operateor>>

(istream&,自定義類);在重載時要注意下面兩點:(1)要對“<<”和“>>”運算符進(jìn)行重載,必須重載為類的友元函數(shù)。(2)重載的友元函數(shù)的返回類型應(yīng)是ostream對象或istream對象的引用,即ostream&或istream&。7.7重載流插入運算符和流提取運算符(1)要對“<<”和“>>”運算符進(jìn)行重載,必須重載為類的友元函數(shù)。cout<<t;或operator<<(cout,t);voidoperator<<(ostream&out,Timer&t){

out<<t.hours<<"hours,"<<t.minutes<<"minutes";}7.7重載流插入運算符和流提取運算符(2)重載的友元函數(shù)的返回類型應(yīng)是ostream對象或istream對象的引用,即ostream&或istream&??聪旅娴恼Z句:intx=5,y=6;cout<<x<<y;C++從左到右讀取輸出語句,這意味著它等同于:(cout<<x)<<y;565.2向上類型轉(zhuǎn)換【例7-8】對于Time類,在【例7-4】的基礎(chǔ)上,增加重載流插入運算符“<<”和流提取運算符“>>”,用“cout<<”輸出Time類的對象,用“cin>>”輸入Time類的對象。#include<iostream.h>

classTime{public:

Time();Time(inth,intm=0);friendTimeoperator+(Time&t1,Time&t2);friendTimeoperator-(Time&t1,Time&t2);friendostream&operator<<(ostream&out,Time&t);friendistream&operator>>(istream&in,Time&t);private:inthours;intminutes;};575.2向上類型轉(zhuǎn)換Time::Time(){hours=minutes=0;}Time::Time(inth,intm){hours=h;minutes=m;}Timeoperator+(Time&t1,Time&t2){Timesum;sum.minutes=t1.minutes+t2.minutes;sum.hours=t1.hours+t2.hours+sum.minutes/60;sum.minutes%=60;returnsum;}Timeoperator-(Time&t1,Time&t2){Timedif;intx1,x2;

x1=t2.hours*60+t2.minutes;x2=t1.hours*60+t1.minutes;dif.minutes=(x2-x1)%60;dif.hours=(x2-x1)/60;

returndif;}585.2向上類型轉(zhuǎn)換ostream&operator<<(ostream&out,Time&t){

out<<t.hours<<"hours,"<<t.minutes<<"minutes";returnout;}istream&operator>>(istream&in,Time&t){

cout<<"inputhoursandminutes:";

in>>t.hours>>t.minutes;

returnin;}595.2向上類型轉(zhuǎn)換intmain(){Timet1,t2,t3,t4;cin>>t1>>t2;cout<<"t1="<<t1<<"\n";cout<<"t2="<<t2<<"\n";t3=t1+t2;cout<<"t3=t1+t2="<<t3<<"\n";t4=t1-t2;cout<<"t4=t1-t2="<<t4<<"\n";return0;}607.8不同類型數(shù)據(jù)間的轉(zhuǎn)換7.8.1系統(tǒng)預(yù)定義類型間的轉(zhuǎn)換7.8.2轉(zhuǎn)換構(gòu)造函數(shù)7.8.3類型轉(zhuǎn)換函數(shù)617.8.1系統(tǒng)預(yù)定義類型間的轉(zhuǎn)換C++提供了兩種轉(zhuǎn)換方式:一種是隱式類型轉(zhuǎn)換(或稱標(biāo)準(zhǔn)類型轉(zhuǎn)換)另一種是顯式類型轉(zhuǎn)換(或稱強(qiáng)制類型轉(zhuǎn)換)627.8.1系統(tǒng)預(yù)定義類型間的轉(zhuǎn)換1.隱式類型轉(zhuǎn)換:主要注意以下幾點:(1)在C++中,將一個標(biāo)準(zhǔn)類型變量的值賦給另一個標(biāo)準(zhǔn)類型變量時,如果這兩種類型兼容,則C++自動將這個值轉(zhuǎn)換為接收變量的類型。(2)如果一個運算符兩邊的運算數(shù)類型不同,先要將其轉(zhuǎn)換為相同的類型,即較低類型轉(zhuǎn)換為較高類型,然后再參加運算。637.8.1系統(tǒng)預(yù)定義類型間的轉(zhuǎn)換1.隱式類型轉(zhuǎn)換:主要注意以下幾點:(3)當(dāng)較低類型的數(shù)據(jù)轉(zhuǎn)換為較高類型時,一般只是形式上有所改變,而不影響數(shù)據(jù)的實質(zhì)內(nèi)容,而較高類型的數(shù)據(jù)轉(zhuǎn)換為較低類型時則可能有些數(shù)據(jù)丟失。(4)如果兩個float型數(shù)參加運算,雖然它們類型相同,但仍要先轉(zhuǎn)成double型再進(jìn)行運算,結(jié)果亦為double型。647.8.1系統(tǒng)預(yù)定義類型間的轉(zhuǎn)換2.顯式類型轉(zhuǎn)換C++提供顯式類型轉(zhuǎn)換,程序員在程序中將一種類型的數(shù)據(jù)轉(zhuǎn)換為另一種指定類型的數(shù)據(jù),其形式為:

類型名(表達(dá)式)如:

int(89.5)

其作用是將89.5轉(zhuǎn)換為整型數(shù)89。65對于用戶自己聲明的類型,編譯系統(tǒng)并不知道怎樣進(jìn)行轉(zhuǎn)換。解決這個問題的關(guān)鍵是讓編譯系統(tǒng)知道怎樣去進(jìn)行這些轉(zhuǎn)換,需要定義專門的函數(shù)來處理。7.8不同類型數(shù)據(jù)間的轉(zhuǎn)換667.8.2轉(zhuǎn)換構(gòu)造函數(shù)通常把只有一個形參的構(gòu)造函數(shù),稱為轉(zhuǎn)換構(gòu)造函數(shù)。利用它,可以將一個其他類型的數(shù)據(jù)轉(zhuǎn)換成一個指定的類的對象。677.8.2轉(zhuǎn)換構(gòu)造函數(shù)先回顧一下以前學(xué)習(xí)過的幾種構(gòu)造函數(shù):默認(rèn)構(gòu)造函數(shù):Rational();//沒有參數(shù)用于初始化的構(gòu)造函數(shù):Rational(intx,inty);用于復(fù)制對象的復(fù)制構(gòu)造函數(shù):Rational(Rational&c);687.8.2轉(zhuǎn)換構(gòu)造函數(shù)轉(zhuǎn)換構(gòu)造函數(shù)只有一個形參,如

Rational(intx){nume=x;deno=1;}其作用是將int型的參數(shù)x轉(zhuǎn)換成Rational類的對象,將x作為有理數(shù)的分子,分母為1。697.8.2轉(zhuǎn)換構(gòu)造函數(shù)轉(zhuǎn)換構(gòu)造函數(shù)只有一個形參,如Rational(intx){nume=x;deno=1;}在類體中,可以有轉(zhuǎn)換構(gòu)造函數(shù),也可以沒有轉(zhuǎn)換構(gòu)造函數(shù),視需要而定。以上幾種構(gòu)造函數(shù)可以同時出現(xiàn)在同一個類中,它們是構(gòu)造函數(shù)的重載。編譯系統(tǒng)會根據(jù)建立對象時給出的實參的個數(shù)與類型選擇形參與之匹配的構(gòu)造函數(shù)。707.8.2轉(zhuǎn)換構(gòu)造函數(shù)使用轉(zhuǎn)換構(gòu)造函數(shù)將一個指定的數(shù)據(jù)轉(zhuǎn)換為類對象的方法如下:

(1)

先聲明一個類。(2)在這個類中定義一個只有一個參數(shù)的構(gòu)造函數(shù),參數(shù)的類型是需要轉(zhuǎn)換的類型,在函數(shù)體中指定轉(zhuǎn)換的方法。(3)在該類的作用域內(nèi)可以用以下形式進(jìn)行類型轉(zhuǎn)換:

類名(指定類型的數(shù)據(jù))就可以將指定類型的數(shù)據(jù)轉(zhuǎn)換為此類的對象。71【例7-9】基于有理數(shù)類的包含轉(zhuǎn)換構(gòu)造函數(shù)和運算符重載的程序。7.8.2轉(zhuǎn)換構(gòu)造函數(shù)72#include<iostream.h>#include<math.h>classrational//聲明有理數(shù)類{public:rational();//無參構(gòu)造函數(shù)rational(intx,inty);//有兩個形參的構(gòu)造函數(shù)rational(intx);//轉(zhuǎn)換構(gòu)造函數(shù)voidprint();//重載函數(shù)作為友元函數(shù)friendrationaloperator+(rationala,rationalb);private:intnum,den;voidoptimi();//有理數(shù)優(yōu)化函數(shù)};73//定義無參構(gòu)造函數(shù)rational::rational(){num=0;den=1;}//定義有兩個形參的構(gòu)造函數(shù)rational::rational(intx,inty){num=x;den=y;}//定義轉(zhuǎn)換構(gòu)造函數(shù)rational::rational(intx){num=x;den=1;}7.8.2轉(zhuǎn)換構(gòu)造函數(shù)74voidrational::print()//輸出有理數(shù){cout<<num;

//當(dāng)分子不為0且分母不為1時才顯示"/分母if(num!=0&&den!=1)cout<<"/"<<den<<"\n";elsecout<<"\n";}//定義作為友元函數(shù)的重載函數(shù)rationaloperator+(rationala,rationalb){rationalr;r.den=a.den*b.den;r.num=a.num*b.den+a.den*b.num;r.optimi();returnr;}voidrational::optimi()//定義有理數(shù)優(yōu)化函數(shù){…}//該函數(shù)的函數(shù)體與【例7-2】相同,在此不再列出7.8.2轉(zhuǎn)換構(gòu)造函數(shù)75intmain(){rationalr1(3,5),r2,r3;intn=3;r2=r1+n;r2.print();r3=n+r1;r3.print();return0;}7.8.2轉(zhuǎn)換構(gòu)造函數(shù)767.8.2轉(zhuǎn)換構(gòu)造函數(shù)說明:為了用構(gòu)造函數(shù)完成類型轉(zhuǎn)換,類內(nèi)至少定義一個只帶一個參數(shù)(或其他參數(shù)都帶有默認(rèn)值)的構(gòu)造函數(shù)。當(dāng)需要類型轉(zhuǎn)換時,系統(tǒng)自動調(diào)用該構(gòu)造函數(shù),創(chuàng)建該類的一個臨時對象,該對象由被轉(zhuǎn)換的值初始化,從而實現(xiàn)了類型轉(zhuǎn)換。777.8.2轉(zhuǎn)換構(gòu)造函數(shù)說明:轉(zhuǎn)換構(gòu)造函數(shù)不僅可以將一個標(biāo)準(zhǔn)類型數(shù)據(jù)轉(zhuǎn)換成類對象,也可以將另一個類的對象轉(zhuǎn)換成轉(zhuǎn)換構(gòu)造函數(shù)所在的類的對象。若有教師類Teacher,學(xué)生類Student,可以定義下面的轉(zhuǎn)換構(gòu)造函數(shù)將Student類轉(zhuǎn)換為Teacher類。Teacher(Student&s){num=s.num;strcpy(name,);sex=s.sex;}787.8.3類型轉(zhuǎn)換函數(shù)通過構(gòu)造函數(shù)可以進(jìn)行類型轉(zhuǎn)換,但是它的轉(zhuǎn)換功能受到限制。由于無法為基本類型定義構(gòu)造函數(shù),因此,不能利用構(gòu)造函數(shù)把自定義類型的數(shù)據(jù)轉(zhuǎn)換成基本類型的數(shù)據(jù),它只能從基本類型(如int,float等)向自定義的類型轉(zhuǎn)換。類型轉(zhuǎn)換函數(shù)則可以用來把源類類型轉(zhuǎn)換成另一種目的類型。797.8.3類型轉(zhuǎn)換函數(shù)類型轉(zhuǎn)換函數(shù)的作用是將一個類的對象轉(zhuǎn)換成另一類型的數(shù)據(jù)。如果已聲明了一個Rational類,可以在Rational類中這樣定義類型轉(zhuǎn)換函數(shù):

operatorint(){returnnume;}807.8.3類型轉(zhuǎn)換函數(shù)在類中,類型轉(zhuǎn)換函數(shù)定義的一般格式為:class類名{…operator<目的類型名>(){ <函數(shù)體>}};817.8.3類型轉(zhuǎn)換函數(shù)關(guān)于類型轉(zhuǎn)換函數(shù),有以下幾點注意事項:(1)類型轉(zhuǎn)換函數(shù)只能定義為一個類的成員函數(shù)而不能定義為類的友元函數(shù)或普通函數(shù),因為轉(zhuǎn)換的主體是本類的對象。(2)類型轉(zhuǎn)換函數(shù)與普通的成員函數(shù)一樣,也可以在類定義體中聲明函數(shù)原型,而將函數(shù)體定義在類外部。827.8.3類型轉(zhuǎn)換函數(shù)關(guān)于類型轉(zhuǎn)換函數(shù),有以下幾點注意事項:(3)類型轉(zhuǎn)換函數(shù)既沒有參數(shù),也不顯式給出返回值類型。(4)類型轉(zhuǎn)換函數(shù)中必須有

“return目的類型的數(shù)據(jù);

”的語句,即必須送回目的類型數(shù)據(jù)作為函數(shù)的返回值。operatorint(){returnnume;}837.8.3類型轉(zhuǎn)換函數(shù)關(guān)于類型轉(zhuǎn)換函數(shù),有以下幾點注意事項:(5)一個類可以定義多個類型轉(zhuǎn)換函數(shù)。C++編譯器將根據(jù)操作數(shù)的類型自動地選擇一個合適的類型轉(zhuǎn)換函數(shù)與之匹配。在可能出現(xiàn)二義性的情況下,應(yīng)顯式地使用類型轉(zhuǎn)換函數(shù)進(jìn)行類型轉(zhuǎn)換。847.8.3類型轉(zhuǎn)換函數(shù)關(guān)于類型轉(zhuǎn)換函數(shù),有以下幾點注意事項:(6)通常把類型轉(zhuǎn)換函數(shù)也稱為類型轉(zhuǎn)換運算符函數(shù),由于它也是重載函數(shù),因此也稱為類型轉(zhuǎn)換運算符重載函數(shù)(或稱強(qiáng)制類型轉(zhuǎn)換運算符重載函數(shù))。857.8.3類型轉(zhuǎn)換函數(shù)下面我們?yōu)椤纠?-9】的有理數(shù)類再加上類型轉(zhuǎn)換函數(shù),即有理數(shù)類的聲明如下:classrational{

//聲明有理數(shù)類public:rational();

//無參構(gòu)造函數(shù)

rational(intx,inty);

//有兩個形參的構(gòu)造函數(shù)

rational(intx);

//轉(zhuǎn)換構(gòu)造函數(shù)

operatorint(){returnnum;}

//類型轉(zhuǎn)換函數(shù)

voidprint();//重載函數(shù)作為友元函數(shù)friendrationaloperator+(rationala,rationalb);private:intnum,den;voidoptimi();};intmain(){rationalr1(3,5),r2,r3;intn=3;r2=r1+n;r2.print();r3=n+r1;r3.print();return0;}867.8.3類型轉(zhuǎn)換函數(shù)轉(zhuǎn)換構(gòu)造函數(shù)和類型轉(zhuǎn)換運算符函數(shù)有一個共同的功能:

當(dāng)需要的時候,編譯系統(tǒng)會自動調(diào)用這些函數(shù),建立一個無名的臨時對象(或臨時變量)。87本章小結(jié)運算符重載函數(shù)的函數(shù)名必須為關(guān)鍵字Operator加一個合法的運算符。當(dāng)用類的成員函數(shù)實現(xiàn)運算符的重載時,運算符重載函數(shù)的參數(shù)(當(dāng)為雙目運算符時)為一個或(當(dāng)為單目運算符時)沒有。運算符的左操作數(shù)一定是對象,因為重載的運算符是該對象的成員函數(shù),而右操作數(shù)是該函數(shù)的參數(shù)。88本章小結(jié)單目運算符“++”和“--”存在前置與后置問題。前置“++”格式為:

返回類型類名::operator++(){……}而后置“++”格式為:

返回類型類名::operator++(int){……}后置“++”中的參數(shù)int僅用作區(qū)分。類聲明和成員函數(shù)定義的分離一般將類的聲明(其中包含成員函數(shù)的聲明)放在指定的頭文件中,用戶如果想用該類,只要把有關(guān)的頭文件包含進(jìn)來。由于在頭文件中包含了類的聲明,因此在程序中就可以用該類來定義對象。由于在類體中包含了對成員函數(shù)的聲明,在程序中就可以調(diào)用這些對象的公用成員函數(shù)。90類聲明和成員函數(shù)定義的分離類庫有兩種:一種是C++編譯系統(tǒng)提供的標(biāo)準(zhǔn)類庫;一種是用戶根據(jù)自己的需要做成的用戶類庫,提供給自己和自己授權(quán)的人使用,這稱為自定義類庫。在程序開發(fā)工作中,類庫是很有用的,它可以減少用戶自己對類和成員函數(shù)進(jìn)行定義的工作量。類聲明和成員函數(shù)定義的分離類聲明和成員函數(shù)定義的分離類庫包括兩個組成部分:(1)類聲明頭文件;(2)已經(jīng)過編譯的成員函數(shù)的定義,它是目標(biāo)文件。用戶只需把類庫裝入到自己的計算機(jī)系統(tǒng)中(一般裝到C++編譯系統(tǒng)所在的子目錄下),并在程序中用#include命令行將有關(guān)的類聲明的頭文件包含到程序中,就可以使用這些類和其中的成員函數(shù),順利地運行程序。93ThankYou!classComplex{public:Complex();//無參構(gòu)造函數(shù)

Complex(double);//轉(zhuǎn)換構(gòu)造函數(shù)Complex(Complex&);//拷貝構(gòu)造函數(shù)

Complex(double,double);//有兩個形參的構(gòu)造函數(shù)Complexoperator-(Complex&,Complex&);//對“-”運算符進(jìn)行重載

friendComplexoperator+(Complex&,Complex&);//對“+”運算符進(jìn)行重載

friendostream&operator<<(ostream&,Complex&);//對“<<”運算符進(jìn)行重載

friendistream&operator>>(istream&,Complex&);//對“>>”運算符進(jìn)行重載private:doublereal,imag;};作業(yè)作業(yè)設(shè)計一個point類,有數(shù)據(jù)成員x、y,類的定義如下:classpoint {public: point(floatxx=0,floatyy=0);voiddisplay();point&operator++(); pointoperator++(int); point&operator--(); pointoperator--(int); friendpointoperator+(intn,point&pt);friendpointoperator+(point&pt,intn);friendostream&operator<<(ostream&out,pointp);friendistream&operator>>(istream&in,pointp); private: floatx,y; };作業(yè)96c.real=real+c2.real;c.imag=imag+c2.imag;c.real=this->real+c2.real;c.imag=this->imag+c2.imag;c.real=c1.real+c2.real;c.imag=c1.imag+c2.imag;c3=c1.operator+(c2);當(dāng)前對象的指針7.2運算符重載的方法97運算符重載函數(shù)可以是:⑴類的成員函數(shù)

但必須要求運算表達(dá)式第一個參數(shù)(即運算符左側(cè)的操作數(shù))是一個類對象,而且與運算符函數(shù)的類型相同。因為必須通過類的對象去調(diào)用該類的成員函數(shù),而且只有運算符重載函數(shù)返回值與該對象同類型,運算結(jié)果才有意義。7.2運算符重載的方法98將一個復(fù)數(shù)和一個整數(shù)相加,如c1+i;成員函數(shù)定義:ComplexComplex::operator+(int&i){returnComplex(real+i,imag);}調(diào)用:c3=c1+i;不能寫成:c3=i+c1;也就是說:數(shù)學(xué)上的交換律不適用如果要計算i+c1的值,必須對“+”運算符再進(jìn)行重載,重載函數(shù)為:

Complexoperator+(Complex&i,Complex&c);此時只能將重載函數(shù)作為友元函數(shù),不能作為成員函數(shù)。99聲明:friendComplexoperator+(Complex&i,Complex&c);友元函數(shù)定義:Complexoperator+(Complex&i,Complex&c){returnComplex(i+c.real,c.imag);}調(diào)用:c3=i+c1;7.2運算符重載的方法100⑵類的友元函數(shù)雙目運算符重載為友元函數(shù)時,在函數(shù)的形參表列中必須有兩個參數(shù)。聲明:friendComplexoperator+(Complex&c1,Complex&c2);友元函數(shù)定義:Complexoperator+(Complex&c1,Complex&c2){returnComplex(c1.real+c2.real,c1.imag+c2.imag);}調(diào)用:c3=c1+c2;形參的順序任意,不要求第一個參數(shù)必須為類對象。要求運算符左側(cè)的操作數(shù)與第一個參數(shù)對應(yīng),運算符右側(cè)的操作數(shù)與第二個參數(shù)對應(yīng)。7.2運算符重載的方法101將一個復(fù)數(shù)和一個整數(shù)相加,如i+c1;聲明:friendComplex

溫馨提示

  • 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. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論