第-章━━運(yùn)算符重載_第1頁
第-章━━運(yùn)算符重載_第2頁
第-章━━運(yùn)算符重載_第3頁
第-章━━運(yùn)算符重載_第4頁
第-章━━運(yùn)算符重載_第5頁
已閱讀5頁,還剩39頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

C++程序設(shè)計第5章(4)

━━運(yùn)算符重載1主要內(nèi)容運(yùn)算符重載的作用運(yùn)算符重載函數(shù)運(yùn)算符重載的實現(xiàn)重載為成員函數(shù)━━雙目運(yùn)算符重載重載為成員函數(shù)━━單目運(yùn)算符重載重載為成員函數(shù)━━“++”和“--”運(yùn)算符重載重載為友元函數(shù)━━雙目運(yùn)算符重載重載為友元函數(shù)━━單目運(yùn)算符重載運(yùn)算符重載的規(guī)則插入運(yùn)算符“<<”的重載━━只能重載為友元函數(shù)提取運(yùn)算符“>>”的重載━━只能重載為友元函數(shù)類型轉(zhuǎn)換函數(shù)自定義字符串類C++標(biāo)準(zhǔn)庫中的string類2運(yùn)算符重載的作用所謂重載,就是重新賦予新的含義。運(yùn)算符重載的必要性:

①對于每一種基本數(shù)據(jù)類型,C++中都作了預(yù)定義,定義了該類型數(shù)據(jù)的編碼方式和存儲方式,以及對它所能進(jìn)行的各種運(yùn)算,即預(yù)定義了運(yùn)算符!使用時必須遵循它的規(guī)定。

【例】整型數(shù):算術(shù)運(yùn)算:+-*/%位運(yùn)算:<<>>&^|~關(guān)系運(yùn)算、邏輯運(yùn)算、賦值運(yùn)算、……

實型數(shù):算術(shù)運(yùn)算:+-*/關(guān)系運(yùn)算、邏輯運(yùn)算、賦值運(yùn)算、……

②在面向?qū)ο蟪绦蛟O(shè)計中,增加了用戶自定義的數(shù)據(jù)類型,即用戶自定義的類,在這類數(shù)據(jù)類型上也需要進(jìn)行相關(guān)運(yùn)算,必須對相關(guān)運(yùn)算符進(jìn)行重新的定義。

【例】

復(fù)數(shù)類:算術(shù)運(yùn)算:+-*/賦值運(yùn)算:=+=-=……3運(yùn)算符重載函數(shù)C++中的重載有:

①函數(shù)重載:使用一個已有的函數(shù)名(即已使用該函數(shù)名定義過函數(shù))來重新定義一個新的函數(shù),使之實現(xiàn)新的功能。這樣同一個函數(shù)名就可以代表不同的函數(shù)。②運(yùn)算符重載:對于C++中預(yù)定義的運(yùn)算符也可以像函數(shù)一樣重載,即定義一個運(yùn)算符重載函數(shù)!運(yùn)算符重載本質(zhì)上就是函數(shù)重載。運(yùn)算符重載函數(shù):

①對于C++預(yù)定義的某個運(yùn)算符,在該運(yùn)算符重載函數(shù)中重新定義其功能,使之能夠作用于某類對象的運(yùn)算。

②基于某個類,可對其相關(guān)的若干個運(yùn)算符進(jìn)行重載,分別定義各運(yùn)算符重載函數(shù),以完成該類對象的各種運(yùn)算。C++中的多態(tài)性有:①編譯時的多態(tài)性:通過“函數(shù)重載”、“運(yùn)算符重載”來實現(xiàn)。②運(yùn)行時的多態(tài)性:通過“繼承機(jī)制+虛函數(shù)”來實現(xiàn)。4運(yùn)算符重載的實現(xiàn)關(guān)于運(yùn)算符重載:

①只能重載C++中預(yù)定義的運(yùn)算符,不能自己臆造運(yùn)算符。②重新賦予運(yùn)算符新的功能是通過函數(shù)實現(xiàn)的,即定義運(yùn)算符重載函數(shù)。③用戶根據(jù)需要對運(yùn)算符賦予一種或多種新的功能,以配合用戶自定義的類,因此運(yùn)算符重載必須作用于類的對象,至少要有一個操作數(shù)是類的對象。

④運(yùn)算符重載后,對于同一個運(yùn)算符,將根據(jù)不同的運(yùn)算對象完成不同的操作,體現(xiàn)了面向?qū)ο蟪绦蛟O(shè)計技術(shù)的多態(tài)性。運(yùn)算符重載的兩種實現(xiàn)方法:

①重載為類的成員函數(shù)。

②重載為類的友元函數(shù)。實現(xiàn)機(jī)制:

①將指定的運(yùn)算表達(dá)式轉(zhuǎn)化為對運(yùn)算符重載函數(shù)的調(diào)用,運(yùn)算對象轉(zhuǎn)化為運(yùn)算符重載函數(shù)的實參。

②編譯系統(tǒng)對運(yùn)算符重載函數(shù)的選擇,遵循函數(shù)重載的選擇規(guī)則。5重載為成員函數(shù)━━雙目運(yùn)算符重載雙目運(yùn)算符重載函數(shù)的定義:

class類名{……

返回值類型

operator運(yùn)算符(

形參

);

};

也可在類外作定義性聲明:

返回值類型

類名::operator運(yùn)算符(

形參

){

函數(shù)體

}雙目運(yùn)算符重載為成員函數(shù):

①只有一個形參,為雙目運(yùn)算符的右操作數(shù)。

②程序中若出現(xiàn)表達(dá)式:c1運(yùn)算符c2則編譯器將其解釋為:c1.

operator運(yùn)算符(

c2

)切記:左操作數(shù)c1必須是該類對象,右操作數(shù)c2可以是類型與形參兼容的數(shù)據(jù)。一起構(gòu)成了運(yùn)算符重載函數(shù)的函數(shù)名聲明在類中,作為該類的成員函數(shù)6【例】(復(fù)數(shù)類、雙目運(yùn)算符重載為成員函數(shù))#include<iostream.h>classComplex{doublereal,image;public:Complex(doubler=0,doublei=0):real(r),image(i){}

voidshow(){cout<<“復(fù)數(shù):(”<<real<<“,”<<image<<“i)\n”;}

Complex&

operator=(

Complex&

);

void

operator+=(

Complex&

);

Complexoperator+(

Complex&

);

Complexoperator+(

double

);

Complex

operator-(

Complex&

);

Complex

operator*(

Complex&

);

Complex

operator/(

Complex&

);};Complex&

Complex::

operator=(Complex&c){

real=c.real;image=c.image;return*this;

}注意:①運(yùn)算符“=”是用于同類兩個對象之間的相互賦值,若類中沒有給出運(yùn)算符“=”重載函數(shù),C++編譯器為每個類生成一個默認(rèn)的operator=重載函數(shù),其語義為按類成員數(shù)據(jù)逐個相互賦值。②雖然這種默認(rèn)的賦值重載函數(shù)對復(fù)數(shù)是合適的,但對某些類這種默認(rèn)的賦值重載可能產(chǎn)生問題,那時就需要自定義賦值重載函數(shù)。7void

Complex::

operator+=(Complex&c){

real+=c.real;image+=c.image;}Complex

Complex::

operator+(Complex&c){

Complextemp(real+c.real,image+c.image);

//創(chuàng)建局部對象temp

returntemp;

}Complex

Complex::

operator+(doubler){

return

Complex(real+r,image);}

//創(chuàng)建無名臨時對象Complex

Complex::

operator-(Complex&c){

return

Complex(real-c.real,image-c.image);

}//創(chuàng)建無名臨時對象ComplexComplex::

operator*(Complex&c){

Complextemp;//創(chuàng)建局部對象temptemp.real=real*c.real-image*c.image;temp.image=real*c.image+image*c.real;

returntemp;

}8Complex

Complex::

operator/(Complex&c){

doubled=c.real*c.real+c.image*c.image;Complextemp;//創(chuàng)建局部對象temptemp.real=(real*c.real+image*c.image)/d;temp.image=(image*c.real-real*c.image)/d;returntemp;

}voidmain(){Complexc1(1,2),c2(3,4),c3(5,6),c4,c5,c6;c1.show();c2.show();c3.show();

c4=c1+c2;

//解釋為:c4.operator=(c1.operator+(c2))

c4.show();

c5=c3-c2+c1;

//解釋為:c5.operator=((c3.operator-(c2)).operator+(c1))c5.show();c6=c3+0.5;//解釋為:c6.operator=(c3.operator+(0.5))c6.show();

(c1*c2).show();//解釋為:c1.operator*(c2)

(c2/c1).show();//解釋為:c2.operator/(c1)

c1+=c2;

//解釋為:c1.operator+=(c2)c1.show();}

運(yùn)行:復(fù)數(shù):(1,2i)復(fù)數(shù):(3,4i)復(fù)數(shù):(5,6i)復(fù)數(shù):(4,6i)復(fù)數(shù):(3,4i)復(fù)數(shù):(5.5,6i)復(fù)數(shù):(-5,10i)復(fù)數(shù):(2.2,-0.4i)復(fù)數(shù):(4,6i)9重載為成員函數(shù)━━單目運(yùn)算符重載單目運(yùn)算符重載函數(shù)的定義:

class類名{……返回值類型

operator運(yùn)算符();};單目運(yùn)算符重載為成員函數(shù):

①程序中若出現(xiàn)表達(dá)式:運(yùn)算符

c1則編譯器將其解釋為:c1.

operator運(yùn)算符()其中:c1必須是該類的對象。

②對于自增“++”和自減“--”運(yùn)算符,存在前置和后置情況,為使C++編譯器能區(qū)分前置和后置情況,定義這兩個運(yùn)算符重載函數(shù)時,必須有所區(qū)別。單目運(yùn)算符因只有一個操作數(shù),故重載為成員函數(shù)時沒有形參。10重載為成員函數(shù)━━“++”和“--”運(yùn)算符重載自增“++”和自減“--”運(yùn)算符重載函數(shù)的定義:

class類名{……

返回值類型operator++();//前置“++”返回值類型operator++(int);//后置“++”

返回值類型operator--();//前置“--”

返回值類型operator--(int);//后置“--”

};說明:對于++和--運(yùn)算符,存在前置和后置情況,為使C++編譯器能區(qū)分前置和后置情況,定義后置運(yùn)算符重載函數(shù)增加一個形參int,其本身沒有實際意義,只作為區(qū)分后置運(yùn)算符的標(biāo)識。11重載為成員函數(shù)━━“++”和“--”運(yùn)算符重載++和--運(yùn)算符重載為成員函數(shù):

①程序中若出現(xiàn)表達(dá)式:++c1

則編譯器將其解釋為:c1.operator++()

其中:c1必須是該類的對象。②程序中若出現(xiàn)表達(dá)式:c1++

則編譯器將其解釋為:c1.operator++(int)其中:c1必須是該類的對象。③程序中若出現(xiàn)表達(dá)式:--c1

則編譯器將其解釋為:c1.operator--()

其中:c1必須是該類的對象。④程序中若出現(xiàn)表達(dá)式:c1--

則編譯器將其解釋為:c1.operator--(int)其中:c1必須是該類的對象。12elsecout<<“c1不等于c2!\n”;name<<“\t成績:”<<s.operator另一類型名();friendComplexoperator-(constComplex&,constComplex&);①重載運(yùn)算符+:str1+str2real;image+=c.標(biāo)準(zhǔn)字符串類string:③格式:str.切記:左操作數(shù)c1必須是該類對象,右操作數(shù)c2可以是類型與形參兼容的數(shù)據(jù)。n--;returnt;}其中:c1必須是該類的對象。一起構(gòu)成了類型轉(zhuǎn)換函數(shù)的函數(shù)名,②對于自增“++”和自減“--”運(yùn)算符,存在前置和后置情況,為了使C++編譯器能區(qū)分前置和后置情況,定義這兩個運(yùn)算符重載函數(shù)時,必須有所區(qū)別。operator--()【例】cout<<3+5<<“123”<<5.②程序中若出現(xiàn)表達(dá)式:c1++【例】(日期類、++、--運(yùn)算符重載為成員函數(shù))#include<iostream.h>classDate{intyear,month,day;

staticintmd[12];//靜態(tài)成員數(shù)據(jù)

public:

Date(inty=1900,intm=1,intd=1):year(y),month(m),day(d)

{if((year%4==0&&year%100!=0)||(year%400==0))md[1]=29;elsemd[1]=28;}

voidset(inty,intm,intd){year=y;month=m;day=d;

if((year%4==0&&year%100!=0)||(year%400==0))md[1]=29;elsemd[1]=28;}

voidshow(){

cout<<year<<“\t年”<<month<<“月”<<day<<“日\t”;

}

Dateoperator++(); //前置++Dateoperator++(int); //后置++Dateoperator--(); //前置--Dateoperator--(int);//后置--};intDate::md[12]={31,28,31,30,31,30,31,31,30,31,30,31};13DateDate::operator++()//前置++{day++;if(month==12&&day>31){++year;month=1;day=1;}if(month!=12&&day>md[month-1]){++month;day=1;}return*this;}DateDate::operator++(int)//后置++{Dated=*this;day++;if(month==12&&day>31){++year;month=1;day=1;}if(month!=12&&day>md[month-1]){++month;day=1;}returnd;}DateDate::operator--()//前置--{day--;if(month==1&&day<1){--year;month=12;day=31;}if(month!=1&&day<1){--month;day=md[month-1];}return*this;}DateDate::operator--(int)//后置--{

Dated=*this;day--;if(month==1&&day<1){--year;month=12;day=31;}if(month!=1&&day<1){--month;day=md[month-1];}returnd;}14voidmain(){inty,dd[12]={31,28,31,30,31,30,31,31,30,31,30,31};cout<<“請輸入年份:”;cin>>y;if((y%4==0&&y%100!=0)||(y%400==0))dd[1]=29;elsedd[1]=28;

Dated;

for(inti=1;i<=12;i++){

d.set(y,i,dd[i-1]);d.show();cout<<“1天后:”;

(++d).show()

;//改為(d++).show();結(jié)果又如何?cout<<endl;

}for(i=1;

i<=12;i++){

d.set(y,i,1);d.show();cout<<“1天前:”;

(--d).show();

//改為(d--).show();結(jié)果又如何?

cout<<endl;

}

}運(yùn)行:請輸入年份:2000↙2000年1月31日1天后:2000年2月1日2000年2月29日1天后:2000年3月1日2000年3月31日1天后:2000年4月1日2000年4月30日1天后:2000年5月1日2000年5月31日1天后:2000年6月1日2000年6月30日1天后:2000年7月1日2000年7月31日1天后:2000年8月1日2000年8月31日1天后:2000年9月1日2000年9月30日1天后:2000年10月1日2000年10月31日1天后:2000年11月1日2000年11月30日1天后:2000年12月1日2000年12月31日1天后:2001年1月1日2000年1月1日1天前:1999年12月31日2000年2月1日1天前:2000年1月31日2000年3月1日1天前:2000年2月29日2000年4月1日1天前:2000年3月31日2000年5月1日1天前:2000年4月30日2000年6月1日1天前:2000年5月31日2000年7月1日1天前:2000年6月30日2000年8月1日1天前:2000年7月31日2000年9月1日1天前:2000年8月31日2000年10月1日1天前:2000年9月30日2000年11月1日1天前:2000年10月31日2000年12月1日1天前:2000年11月30日15重載為友元函數(shù)━━雙目運(yùn)算符重載雙目運(yùn)算符重載函數(shù)的定義:

class類名{……

friend返回值類型operator運(yùn)算符(形參1,形參2);

};一般在類外對友元函數(shù)作定義性聲明:

返回值類型operator運(yùn)算符(形參1,形參2){

函數(shù)體

}雙目運(yùn)算符重載為友元函數(shù):①形參有2個,其中:“形參1”是運(yùn)算符的左操作數(shù),“形參2”是運(yùn)算符的右操作數(shù)。

②程序中若出現(xiàn)表達(dá)式:c1運(yùn)算符c2則編譯器將其解釋為:operator運(yùn)算符(

c1

,

c2

)

切記:

若c1不是、而c2是某類的對象,則該函數(shù)必須是該類的友元函數(shù)。友元函數(shù)不是成員函數(shù),不要加“類名::”聲明在類中,作為該類的成員函數(shù)16【例】(復(fù)數(shù)類、雙目運(yùn)算符重載為友元函數(shù))#include<iostream.h>

classComplex{doublereal,image;

public:Complex(doubler=0,doublei=0):real(r),image(i){}voidshow(){cout<<“復(fù)數(shù):(”<<real<<“,”<<image<<“i)\n”;}

friendvoidoperator-=(Complex&,constComplex&);friendComplexoperator-(constComplex&,constComplex&);friendComplexoperator-(constComplex&,double);friendComplexoperator-(double,constComplex&);friendbooloperator==(constComplex&,constComplex&);friendbooloperator!=(constComplex&,constComplex&);};注意:在函數(shù)形參表中,一般將其值無需修改的形參對象定義為const。目的是:若在函數(shù)中發(fā)生誤操作,出現(xiàn)修改該形參對象數(shù)據(jù)時,編譯系統(tǒng)將給出錯誤信息。

注意:在函數(shù)形參表中,使用引用類型的對象作為函數(shù)的形參,可以提高函數(shù)的運(yùn)行效率。17voidoperator-=(Complex&c1,constComplex&c2){

c1.real-=c2.real;c1.image-=c2.image;}Complexoperator-(constComplex&c1,constComplex&c2){

Complextemp(c1.real-c2.real,c1.image-c2.image);

returntemp;

}Complexoperator-(constComplex&c,doubler){return

Complex(c.real-r,c.image);}Complexoperator-(doubler,constComplex&c){

return

Complex(r-c.real,-c.image);

}booloperator==(

constComplex&c1,constComplex&c2

){

if(c1.real==c2.real&&c1.image==c2.image)returntrue;elsereturnfalse;

}booloperator!=(constComplex&c1,constComplex&c2){

if(c1.real!=c2.real||c1.image!=c2.image)returntrue;elsereturnfalse;}18voidmain(){Complexc1(1,2),c2(3,4),c3(5,6),c4,c5,c6;c1.show();c2.show();c3.show();

c4=c1-c2;

//解釋為:c4.operator=(operator-(c1,c2))c4.show();

c5=c3-c2-2;

//解釋為:c5.operator=(operator-(operator-(c3,c2),2))c5.show();

c6=2-c1;

//解釋為:c6.operator=(operator-(2,c1))c6.show();if(c1==c2)//解釋為:operator==(c1,c2)cout<<“c1等于c2!\n”;elsecout<<“c1不等于c2!\n”;if(c1!=c3)//解釋為:operator!=(c1,c3)cout<<“c1不等于c3!\n”;elsecout<<“c1等于c3!\n”;

c2-=c1;

//解釋為:operator-=(c2,c1)c2.show();}

運(yùn)行:復(fù)數(shù):(1,2i)復(fù)數(shù):(3,4i)復(fù)數(shù):(5,6i)復(fù)數(shù):(-2,-2i)復(fù)數(shù):(0,2i)復(fù)數(shù):(1,-2i)c1不等于c2!c1不等于c3!復(fù)數(shù):(2,2i)19重載為友元函數(shù)━━單目運(yùn)算符重載單目運(yùn)算符重載函數(shù)的定義:

class類名{……

friend返回值類型operator運(yùn)算符(形參);};單目運(yùn)算符重載為友元函數(shù):

①程序中若出現(xiàn)表達(dá)式:運(yùn)算符

c1則編譯器將其解釋為:operator運(yùn)算符(

c1

)

②對于自增“++”和自減“--”運(yùn)算符,存在前置和后置情況,為了使C++編譯器能區(qū)分前置和后置情況,定義這兩個運(yùn)算符重載函數(shù)時,必須有所區(qū)別。單目運(yùn)算符只有一個操作數(shù),故重載為友元函數(shù)時對應(yīng)一個形參。20重載為友元函數(shù)━━“++”和“--”運(yùn)算符重載自增“++”和自減“--”運(yùn)算符重載函數(shù)的定義:

class類名{……

friend返回值類型operator++(形參);//前置“++”

friend返回值類型operator++(形參,int

);//后置“++”

friend返回值類型operator--(形參);//前置“--”

friend返回值類型operator--(形參,int);//后置“--”

};++和--運(yùn)算符重載為友元函數(shù):

①程序中若出現(xiàn)表達(dá)式:++c1

則編譯器將其解釋為:operator++(

c1

)②程序中若出現(xiàn)表達(dá)式:c1++

則編譯器將其解釋為:operator++(

c1

,int

)21【例】(計數(shù)器類、“++”和“--”重載為友元函數(shù))#include<iostream.h>classCounter{intn;

public:

Counter(intx=0){n=x;}

voidshow(){cout<<“計數(shù)值=\t”<<n<<endl;}

friendCounteroperator++(Counter&c){

c.n++;returnc;

}

friendCounteroperator++(Counter&c,int)

{

Countert=c;c.n++;returnt;

}

friendCounteroperator--(Counter&c){

c.n--;returnc;

}

friendCounteroperator--(Counter&c,int)

{

Countert=c;c.n--;returnt;

}

};voidmain(){Counterc1(5),c2(10),c3;(++c1).show();c1.show();(c2++).show();c2.show();(--c3).show();c3.show();(c3--).show();c3.show();}運(yùn)行:計數(shù)值=6計數(shù)值=6計數(shù)值=10計數(shù)值=11計數(shù)值=-1計數(shù)值=-1計數(shù)值=-1計數(shù)值=-222運(yùn)算符重載的規(guī)則C++中運(yùn)算符重載的規(guī)則:

①只能重載C++預(yù)定義的運(yùn)算符,不能自己臆造運(yùn)算符。②不允許重載的運(yùn)算符有:?:(三目運(yùn)算符).(成員運(yùn)算符).*(成員指針運(yùn)算符)

::(域運(yùn)算符)sizeof()(求字節(jié)數(shù)運(yùn)算符)

③運(yùn)算符重載不能改變操作數(shù)的個數(shù)、運(yùn)算符的優(yōu)先級、運(yùn)算符的結(jié)合性和運(yùn)算符的語法結(jié)構(gòu)。

④運(yùn)算符=、()、[]、—>

只能重載為成員函數(shù),不能重載為友元函數(shù)!

⑤賦值運(yùn)算符“=”,其重載函數(shù)一般可省略不寫,編譯器為每個類自動生成一個默認(rèn)的“operator=”重載函數(shù),其語義為按類成員數(shù)據(jù)依次相互賦值。注意,若某類對象的成員數(shù)據(jù)中有指向動態(tài)分配的數(shù)據(jù)時,對象之間就不能直接相互賦值,否則在程序執(zhí)行中會出現(xiàn)運(yùn)行錯誤,此時不能使用系統(tǒng)給出的默認(rèn)賦值重載函數(shù),必須在類中自定義賦值重載函數(shù),且只能重載為成員函數(shù)?。ê罄m(xù)章節(jié)介紹)

⑥運(yùn)算符流插入<<、流提取>>

只能重載為友元函數(shù)!23class類名{doublereal,image;#include<string>插入運(yùn)算符“<<”的重載━━只能重載為友元函數(shù)重載為友元函數(shù)━━“++”和“--”運(yùn)算符重載【例】復(fù)數(shù)類:算術(shù)運(yùn)算:+-*/功能:將新創(chuàng)建的string類對象初始化為空串。單目運(yùn)算符重載函數(shù)的定義:……{Moneym1(1,22,33),m2(2,44,66);數(shù)對復(fù)數(shù)是合適的,但對某些提取運(yùn)算符“>>”的重載━━只能重載為友元函數(shù)last=i;operator=((c3.char&operator[](int);mystring&operator+=(constmystring&);{out<<ms.插入運(yùn)算符“<<”的重載━━只能重載為友元函數(shù)關(guān)于表達(dá)式cout<<基本類型數(shù)據(jù)、cout<<字符串:

①插入運(yùn)算符“<<”在C++中是預(yù)定義為位左移運(yùn)算符,由于在C++類庫的輸出流類ostream中對其進(jìn)行了重載,使之能用作基本類型數(shù)據(jù)、字符串的輸出運(yùn)算符。

②在頭文件iostream.h/iostream中定義了四個全局流對象(cin、cout、cerr、clog),其中cout、cerr、clog都是輸出流類ostream的對象。③在輸出流類ostream中,對往輸出流中插入“<<”基本類型數(shù)據(jù)、字符串分別進(jìn)行重載。在中重載了19種不同形式的成員函數(shù),重載“<<”函數(shù)原型為:

ostream&operator<<(int);

ostream&operator<<(double);

……

ostream&operator<<(char*);

【例】cout<<3+5<<“123”<<5.5;分析表達(dá)式的執(zhí)行過程。返回值為ostream類的對象引用,實際上就是返回當(dāng)前輸出流!24插入運(yùn)算符“<<”的重載━━只能重載為友元函數(shù)④輸出流類ostream的聲明在頭文件iostream.h/iostream中,若要對基本類型數(shù)據(jù)、字符串進(jìn)行輸出操作,程序中必須包含該頭文件。

⑤注意:在表達(dá)式cout<<基本類型數(shù)據(jù)、cout<<字符串中,左操作數(shù)是輸出流類ostream的對象cout,右操作數(shù)才是基本類型數(shù)據(jù)、字符串。

⑥對于用戶自定義類型的數(shù)據(jù)(即類的對象),不能直接用插入運(yùn)算符“<<”進(jìn)行輸出,即不支持表達(dá)式cout<<某類對象,必須在該類中對插入運(yùn)算符“<<”重載,由于左操作數(shù)為cout,非本類對象,因此只能重載為友元函數(shù)!

⑦在用戶自定義的類中聲明重載運(yùn)算符“<<”為友元函數(shù):

friendostream&operator<<(

ostream&,自定義類&)25提取運(yùn)算符“>>”的重載━━只能重載為友元函數(shù)關(guān)于表達(dá)式cin>>基本類型變量名、cin>>字符數(shù)組名:

①提取運(yùn)算符“>>”在C++中是預(yù)定義為位右移運(yùn)算符,由于在C++類庫的輸入流類istream中對其進(jìn)行了重載,使之能用作基本類型數(shù)據(jù)、字符串的輸入運(yùn)算符。

②在頭文件iostream.h/iostream中定義了四個全局流對象(cin、cout、cerr、clog),其中cin是輸入流類istream的對象。③在輸入流類istream中,對從輸入流中提取“>>”基本類型數(shù)據(jù)、字符串分別進(jìn)行重載。在中重載了18種不同形式的成員函數(shù),重載“>>”函數(shù)原型為:

istream&operator>>(int)

istream&operator>>(double)

……

istream&operator>>(

char*)

【例】inta;doubleb;charc;cin>>a>>b>>c;分析表達(dá)式的執(zhí)行過程。返回值為istream類的對象引用,實際上就是返回當(dāng)前輸入流!26提取運(yùn)算符“>>”的重載━━只能重載為友元函數(shù)④輸入流類istream的聲明在頭文件iostream.h/iostream中,若要對基本類型數(shù)據(jù)、字符串進(jìn)行輸入操作,程序中必須包含該頭文件。

⑤注意:在表達(dá)式cin>>基本類型變量名、cin>>字符數(shù)組名中,左操作數(shù)是輸入流類istream的對象cin,右操作數(shù)才是基本類型變量名、字符數(shù)組名。

⑥對于用戶自定義類型的變量(即類的對象),不能直接用提取運(yùn)算符“>>”進(jìn)行輸入,即不支持表達(dá)式cin>>某類對象名,必須在該類中對提取運(yùn)算符“>>”重載,由于左操作數(shù)為cin,非本類對象,因此只能重載為友元函數(shù)!

⑦在用戶自定義的類中聲明提取運(yùn)算符“>>”為友元函數(shù):

friend

istream&

operator>>(

istream&

,自定義類&

)27【例】(定義學(xué)生類,使之能用插入運(yùn)算符“<<”來整體輸出一個學(xué)生的資料,能用提取運(yùn)算符“>>”來整體輸入一個學(xué)生的資料。)#include<iostream.h>#include<string.h>classStudent{intid;charname[10];intscore;

public:

Student(inti=0,char*na=0,ints=0){id=i;if(na)strcpy(name,na);score=s;}

friendbooloperator<(Student&,Student&);

friendistream&operator>>(istream&,Student&);friendostream&operator<<(

ostream&,Student&);};booloperator<(Student&s1,Student&s2){

if(s1.score<s2.score)returntrue;elsereturnfalse;

}28istream&operator>>(istream&in,Student&s){cout<<“請輸入學(xué)號、姓名、成績:”;

in>>s.id>>>>s.score;returnin;

}ostream&operator<<(ostream&out,Student&s){

out<<“學(xué)號:”<<s.id<<“\t姓名:”<<<<“\t成績:”<<s.score<<endl;returnout;

}voidmain(){Students[4],t;inti,j;for(i=0;i<4;i++)cin>>s[i];cout<<“排序前:\n”;for(i=0;i<4;i++)cout<<s[i];for(i=0;i<3;i++)for(j=i+1;j<4;j++)if(s[i]<s[j]){t=s[i];s[i]=s[j];s[j]=t;}cout<<“排序后:\n”;for(i=0;i<4;i++)cout<<s[i];}運(yùn)行:請輸入學(xué)號、姓名、成績:111aaa88↙請輸入學(xué)號、姓名、成績:222bbb99↙請輸入學(xué)號、姓名、成績:333ccc77↙請輸入學(xué)號、姓名、成績:444ddd98↙排序前:學(xué)號:111姓名:aaa成績:88學(xué)號:222姓名:bbb成績:99學(xué)號:333姓名:ccc成績:77學(xué)號:444姓名:ddd成績:98排序后:學(xué)號:222姓名:bbb成績:99學(xué)號:444姓名:ddd成績:98學(xué)號:111姓名:aaa成績:88學(xué)號:333姓名:ccc成績:7729類型轉(zhuǎn)換函數(shù)類型轉(zhuǎn)換函數(shù)的作用:類型轉(zhuǎn)換函數(shù)是類的成員函數(shù),其功能是將該類的對象數(shù)據(jù),轉(zhuǎn)換成另一類型的數(shù)據(jù)。所謂“另一類型”可以是基本數(shù)據(jù)類型,也可以是已定義的構(gòu)造數(shù)據(jù)類型。類型轉(zhuǎn)換函數(shù)的定義:

class類名{……

operator另一類型名();

};

一起構(gòu)成了類型轉(zhuǎn)換函數(shù)的函數(shù)名,其中另一類型指轉(zhuǎn)換后的數(shù)據(jù)類型。沒有形參,也不能指定返回值類型,其返回值類型由operator后面的“另一類型”確定。30自增“++”和自減“--”運(yùn)算符重載函數(shù)的定義:class類名聲明在類中,作為該類的成員函數(shù)2000年11月30日1天后:2000年12月1日所謂“另一類型”可以是基本數(shù)據(jù)類型,也可以是已定義的構(gòu)造數(shù)據(jù)類型。show();c2.do{k=str[i]-ms.④輸入流類istream的聲明在頭文件iostream.voidmain()【例】(自定義一個簡單的字符串類)下標(biāo)0123456789101112131415operator=(c3.do{k=str[i]-ms.【例】(類型轉(zhuǎn)換函數(shù))#include<iostream.h>classMoney{ intyuan,jiao,fen;

public:

Money(inty=0,intj=0,intf=0){yuan=y;jiao=j;fen=f;}voidshow(){cout<<yuan<<“元”<<jiao<<“角”<<fen<<“分\t”;}

operatorfloat() {return(yuan+jiao/10.+fen/100.);}

operatorint() {return(yuan*100+jiao*10+fen);}};voidmain(){Moneym1(1,22,33),m2(2,44,66);m1.show();cout<<“=\t”<<float(m1)<<“(元)\n”;m2.show();cout<<“=\t”<<(int)m2

<<“(分)\n”;}運(yùn)行:1元22角33分=3.53(元)2元44角66分=706(分)31自定義字符串類【例】(自定義一個簡單的字符串類mystring)★成員數(shù)據(jù):

charstr[N];存放字符串的數(shù)組容器,其中N為常量

②intmaxsize;數(shù)組中最多可容納的元素數(shù),maxsize=N

③intlast;數(shù)組容器中已存放字符的個數(shù),空串時last=0★成員函數(shù):

①構(gòu)造函數(shù):mystring();

mystring(char*);mystring(mystring&);//拷貝構(gòu)造可省略不寫②析構(gòu)函數(shù):~mystring();//析構(gòu)函數(shù)可省略不寫

bG8A+3a

H\0

str數(shù)組容器maxsize=16下標(biāo)0123456789101112131415

last=732自定義字符串類③成員重載運(yùn)算符:mystring

operator+(mystring&);

mystring&

operator+=(mystring&);

mystring

operator=(mystring&);//重載=運(yùn)算符可省略不寫

mystring&

operator=(char*);

bool

operator>(mystring&);

bool

operator==(mystring&);

char&

operator[](int);④友元重載運(yùn)算符:istream&

operator>>(istream&,mystring&);

ostream&

operator<<(ostream&,mystring&);33【例】(自定義一個簡單的字符串類)#include<iostream.h>#defineN10classmystring{charstr[N];intmaxsize;intlast;public:mystring();mystring(constchar*

);mystringoperator+(

constmystring&)

const;mystring&operator+=(

constmystring&

);mystring&operator=

(

constchar*

);booloperator>(

constmystring&

)

const;booloperator==(

constmystring&

)

const;char&operator[]

(int);

friendistream&operator>>(istream&,mystring&);

friendostream&operator<<(ostream&,mystring&);};注意:將形參定義為指向常量的指針、常對象引用,目的是防止在函數(shù)中修改該形參對象的成員數(shù)據(jù)。注意:當(dāng)成員函數(shù)中無需修改當(dāng)前對象的成員數(shù)據(jù)時,可定義為const成員函數(shù),這樣做目的是:防止在函數(shù)中發(fā)生誤操作,出現(xiàn)修改成員數(shù)據(jù)時,編譯將給出錯誤信息。

34//構(gòu)造函數(shù),將新創(chuàng)建的字符串對象初始化為空串mystring::mystring(){maxsize=N;str[0]=‘\0’;last=0;}//構(gòu)造函數(shù),用C語言風(fēng)格的字符串來初始化新創(chuàng)建的字符串對象mystring::mystring(

constchar*s

)

//當(dāng)s所指向的字符串過長時,需截尾處理{maxsize=N;inti=0;

while((i<maxsize)&&(str[i]=s[i]))i++;last=i;if(i>=maxsize){last=i-1;str[last]=‘\0’;}//截尾}//重載運(yùn)算符+,將兩個字符串對象拼接產(chǎn)生第三個字符串對象

mystring

mystring::operator+

(

constmystring&ms

)

const{mystringt;

inti=0,k=0;

while((i<t.maxsize)&&(t.str[i]=str[k])){i++;k++;}

if(i>=t.maxsize){t.last=i-1;t.str[t.last]=‘\0’;returnt;}

//截尾k=0;

while((i<t.maxsize)&&(t.str[i]=ms.str[k])){i++;k++;}t.last=i;

if(i>=t.maxsize){t.last=i-1;t.str[t.last]=‘\0’;}

//截尾returnt;}35//重載運(yùn)算符+=,將一個字符串對象拼接到當(dāng)前字符串對象的尾部

mystring&

mystring::operator+=

(

constmystring&ms

)

{inti=last,k=0;

while((i<maxsize)&&(str[i]=ms.str[k])){i++;k++;}last=i;

if(i>=maxsize){last=i-1;str[last]=‘\0’;}

//截尾return*this;}//重載運(yùn)算符=,將C語言風(fēng)格的字符串賦值給當(dāng)前字符串對象

mystring&

mystring::operator=

(constchar*s

)

{inti=0;

while((i<maxsize)&&(str[i]=s[i]))i++;last=i;

if(i>=maxsize){last=i-1;str[last]=‘\0’;}

//截尾return*this;}//重載運(yùn)算符[],返回當(dāng)前字符串對象中某下標(biāo)處字符的引用,不檢查是否越界

char&

mystring::operator[](

intk

){returnstr[k];}36//重載運(yùn)算符>,比較兩個字符串對象的大小bool

mystring::operator>(

constmystring&ms

)

const{

inti=0,k;

do{k=str[i]-ms.str[i];i++;

}while(k==0&&i<last&&i<ms.last);if(k>0)returntrue;if(i!=last&&i==ms.last)returntrue;

returnfalse;}//重載運(yùn)算符==,比較兩個字符串對象是否相等bool

mystring::operator==(

constmystring&ms

)

const{

inti=0,k;

do{k=str[i]-ms.str[i];i++;

}while(k==0&&i<last&&i<ms.last);if(k!=0)returnfalse;if(i==last&&i==ms.last)returntrue;

returnfalse;}37//重載運(yùn)算符>>,實現(xiàn)字符串對象的整體輸入,超出對象容量時做截尾處理istream&

operator>>(istream&in,mystring&ms){inti=0;charc;c=in.get();

while((i<ms.maxsize)&&(c!=32)&&(c!=‘\n’)){ms.str[i]=c;i++;c=in.get();}

if(i>=ms.maxsize)

{ms.last=i-1;ms.str[ms.last]=‘\0’;}

//截尾

else{

ms.last=i;ms.str[ms.last]=‘\0’;

}

returnin;}//重載運(yùn)算符<<,實現(xiàn)字符串對象的整體輸出ostream&

operator<<(ostream&out,mystring&ms){out<<ms.str;

returnout;}38voidmain(){mystrings1(“ABCD”),s2(“1234567”),s3;cout<<“s1=”<<

溫馨提示

  • 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

提交評論