




版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 副經(jīng)理聘用合同范本
- 公司維修勞務(wù)合同范本
- 加工生產(chǎn)毛巾合同范本
- 與律師服務(wù)合同范本
- 協(xié)助運(yùn)作合同范本
- 化妝品授權(quán)合同范本
- 前臺銷售合同范本
- 醫(yī)院醫(yī)用柜合同范例
- 加盟合同范本6
- 包銷合同范本模板
- 《駱駝祥子》通讀指導(dǎo)手冊
- 股東會會議系列文件(通知、議程、簽到表、表決票、決議)
- 非法占用農(nóng)田建房舉報信范文
- 伐樹工程施工合同范本
- 數(shù)據(jù)挖掘(第2版)PPT全套完整教學(xué)課件
- 工程開工報告(5篇)
- 配電箱試驗項目
- 運(yùn)動技能學(xué)習(xí)與控制課件第一章運(yùn)動技能學(xué)習(xí)與控制概述
- 溫室大棚花卉苗圃采暖方案空氣源熱泵
- BEC商務(wù)英語高級考試歷年真題
- 初二地理中考復(fù)習(xí)備考策略與計劃
評論
0/150
提交評論