版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
C++特殊操作符的重載C++特殊操作符賦值操作符“=”訪問(wèn)數(shù)組元素操作符“[]”類成員訪問(wèn)操作符“->”函數(shù)調(diào)用操作符“()”動(dòng)態(tài)對(duì)象創(chuàng)建與撤銷(xiāo)操作符new與delete類型轉(zhuǎn)換操作符賦值操作符“=”的重載同一個(gè)類的兩個(gè)對(duì)象如何賦值?Aa,b;......a=b;//?C++編譯程序會(huì)為每個(gè)類定義一個(gè)隱式的賦值操作,其行為是:逐個(gè)成員進(jìn)行賦值操作。對(duì)于普通成員,它采用常規(guī)的賦值操作。對(duì)于成員對(duì)象,則調(diào)用該成員對(duì)象類的賦值操作進(jìn)行成員對(duì)象的賦值操作。隱式的賦值操作有時(shí)不能滿足要求!例如,對(duì)下面String類的對(duì)象進(jìn)行賦值操作時(shí),系統(tǒng)提供的隱式賦值操作存在問(wèn)題:classString{ intlen; char*str; public: String(char*s) {len=strlen(s); str=newchar[len+1]; strcpy(str,s); }
~String(){delete[]str;str=NULL;}};......Strings1("xyz"),s2("abcdefg");.......s1=s2;s1.str原來(lái)所指向的空間成了“孤兒”(內(nèi)存泄露)s1和s2互相干擾s1和s2消亡時(shí),"abcdefg"所在的空間將會(huì)被釋放兩次!lenstrlenstrs1s2xyz37abcdefg7解決上面問(wèn)題的辦法是自己定義賦值操作符重載函數(shù):classString{......String&operator=(constString&s){ if(&s==this)return*this;//防止自身賦值:a=a
delete[]str; str=newchar[s.len+1]; strcpy(str,s.str);len=s.len; return*this;}};上面的返回值類型能是void嗎?為什么是String并且是它的引用?為了允許下面的操作:
a=b=c和(a=b)=c自定義的賦值操作符重載函數(shù)不會(huì)自動(dòng)地去進(jìn)行成員對(duì)象的賦值操作,必須要在自定義的賦值操作符重載函數(shù)中顯式地給出,例如:classA{......};classB{ Aa; intx,y; public: ...... B&operator=(constB&b) { if(&b
==this)return*this;a=b.a;//調(diào)用A類的賦值操作符重載函數(shù)來(lái)實(shí)現(xiàn)成員對(duì)象的賦值。
x=b.x; y=b.y; return*this; }};
一般來(lái)講,需要自定義拷貝構(gòu)造函數(shù)的類通常也需要自定義賦值操作符重載函數(shù)。
注意:要區(qū)別下面兩個(gè)“=”的不同含義。Aa;Ab=a;//初始化,等價(jià)于:Ab(a);,調(diào)用拷貝構(gòu)造函數(shù)。......b=a;//賦值,調(diào)用賦值操作符=重載函數(shù)。下面對(duì)b2.a進(jìn)行初始化的區(qū)別是什么?classA{......};classB{Aa;
intx,y;
......
B(){......}
B(constB&b):a(b.a)
B(constB&b)
{x=b.x;
y=b.y;
a=b.a;
}};Bb1;Bb2(b1);//這里還要調(diào)用A的默認(rèn)構(gòu)造函數(shù)對(duì)a初始化!//這里是調(diào)用A的賦值操作給a賦值訪問(wèn)數(shù)組元素操作符“[]”的重載
對(duì)于由具有線性關(guān)系的元素所構(gòu)成的對(duì)象,可通過(guò)重載下標(biāo)操作符“[]”來(lái)實(shí)現(xiàn)對(duì)其元素的訪問(wèn)。例如:classString{ intlen; char*str;
public:
...... char&operator[](inti){ returnstr[i];} charoperator[](inti)const{ returnstr[i];}//用于常量對(duì)象};......Strings("abcd");...s[2]...//訪問(wèn)s中的'c'再例如:classVector//向量類{ int*p_data; intnum; public: ...... int&operator[](inti)//訪問(wèn)向量第i個(gè)元素。
{ returnp_data[i]; }};......Vectorv(10);.........v[2]...//訪問(wèn)向量第三個(gè)元素對(duì)于常量對(duì)象的場(chǎng)合要加上另一個(gè)重載函數(shù):intoperator[](inti)const{ returnp_data[i];}classMatrix//矩陣類{
?p_data;//表示矩陣數(shù)據(jù)
introw,col;//表示矩陣的行數(shù)和列數(shù)
public:
Matrix(intr,intc){
?
} ~Matrix(){?
}
Vector
&operator[](inti)//訪問(wèn)矩陣元素。
{return?;}
......};......Matrixm(10,20);.........m[2][3]...//訪問(wèn)矩陣第三行、第四列元素。如何能這樣使用?重載間接類成員訪問(wèn)操作符“->”
--智能指針“->”為一個(gè)雙目操作符:第一個(gè)操作數(shù)為一個(gè)指向類或結(jié)構(gòu)的指針。第二個(gè)操作數(shù)為第一個(gè)操作數(shù)所指向的類或結(jié)構(gòu)的成員。Aa,*p=&a;p->f();//假設(shè)f是A中的一個(gè)成員函數(shù)針對(duì)某個(gè)類重載“->”操作符,可以實(shí)現(xiàn)一種智能指針(smartpointers):對(duì)該類的對(duì)象實(shí)施“->”操作能訪問(wèn)它“指向”的另一個(gè)對(duì)象的成員。通過(guò)該對(duì)象去訪問(wèn)它指向的對(duì)象的成員之前能做一些額外的事情。(智能)Bb(&a);b->f();//b是個(gè)智能指針對(duì)象,訪問(wèn)對(duì)象a的f例:在程序執(zhí)行的某個(gè)時(shí)刻獲取某個(gè)對(duì)象被訪問(wèn)的次數(shù)classA{ intx,y; public: voidf(); voidg();};voidfunc(A*p){......p->f();
......p->g();......}......Aa;func(&a);......//調(diào)用完func后,如何知道在func中訪問(wèn)了a多少次?一種解決方案:在類A中加一個(gè)計(jì)數(shù)器countclassA{ intx,y; intcount;public: A(){count=0;...} voidf(){count++;...} voidg(){count++;...} intnum_of_access()const{returncount;}};voidfunc(A*p)
{......p->f();......p->g();......}......Aa;func(&a);...a.num_of_access()...//獲得對(duì)a的訪問(wèn)次數(shù)問(wèn)題:要修改類A,每個(gè)成員函數(shù)都要加上:count++;如果類A中有外界可訪問(wèn)的數(shù)據(jù)成員,無(wú)法對(duì)其訪問(wèn)計(jì)數(shù)!p->z;}intz;更好的解決方案:定義一個(gè)智能指針類classB//智能指針類{ A*p_a;//指向A類對(duì)象的指針 intcount; public: B(A*p) { p_a=p;count=0; }
A*operator->()//操作符“->”的重載函數(shù),按單目操作符重載!
{ count++;
returnp_a; } intnum_of_a_access()const { returncount; }};voidfunc(B&p)//注意:p是個(gè)B類對(duì)象!{...p->f();...p->g();...}不修改類AclassA{ intx,y; public: voidf(); voidg();};Aa;A*p=&a;//p是普通的指針p->f();//訪問(wèn)a的成員fBb(&a);//b為一個(gè)智能指針,
//它指向了ab->f();//訪問(wèn)a的成員f,等價(jià)于//b.operator->()->f();func(b);//把b傳給func...b.num_of_a_access()... //獲得對(duì)a的訪問(wèn)次數(shù)p->z;intz;//也能對(duì)數(shù)據(jù)成員的訪問(wèn)進(jìn)行計(jì)數(shù)!為了完全模擬普通的指針功能,針對(duì)智能指針類,還可以重載“*”(對(duì)象間接訪問(wèn))、“[]”、“+”、“-”、“++”、“--”、......等操作符:classB//智能指針類{ A*p_a;public:
B(A*p){p_a=p;} A*operator->(){returnp_a;}
A&operator*()
{return*p_a; } A&operator[](inti)
{returnp_a[i]; }
......};Aa[10];A*p=&a[0];//普通指針p->f();//a[0].f();(*p).f();//a[0].f();p[2].f();//a[2].f();p=p+1;p++;......
Bb(&a[0]);//智能指針 //可寫(xiě)成:Bb=&a[0];b->f();//a[0].f();(*b).f();//a[0].f();b[2].f();//a[2].f();b=b+1;b++......重載函數(shù)調(diào)用操作符“()”
--函數(shù)對(duì)象在C++中,把函數(shù)調(diào)用也作為一種操作符來(lái)看待:操作符為(),操作數(shù)為函數(shù)名及各個(gè)實(shí)參,結(jié)果為函數(shù)返回值z(mì)=f(x,y);重載函數(shù)調(diào)用操作符之后,相應(yīng)類的對(duì)象就可當(dāng)作函數(shù)來(lái)使用了。例如:classA{ intvalue; public: A(){value=0;} A(inti){value=i;} intoperator()(intx)//函數(shù)調(diào)用操作符()的重載函數(shù)
{returnx+value; }};......Aa(3);//a是個(gè)對(duì)象,但可以當(dāng)函數(shù)來(lái)使用它c(diǎn)out<<a(10)<<endl;//a(10)將會(huì)去調(diào)用A中的函數(shù)調(diào)用操作符
//重載函數(shù),10作為實(shí)參,返回13函數(shù)調(diào)用操作符重載主要用于具有函數(shù)性質(zhì)的對(duì)象(函數(shù)對(duì)象,functor),該對(duì)象通常只有一個(gè)操作,它除了具有一般函數(shù)的行為外,它還可以擁有狀態(tài)。例如,下面是一個(gè)能產(chǎn)生隨機(jī)數(shù)的對(duì)象:classRandomNum{ unsignedintseed;//狀態(tài) public: RandomNum(unsignedinti){seed=i;}unsignedintoperator()()//函數(shù)調(diào)用操作符重載
{seed=(25173*seed+13849)%65536; returnseed;}};......RandomNumrandom_num(1);//創(chuàng)建一個(gè)函數(shù)對(duì)象...random_num()...//利用函數(shù)對(duì)象產(chǎn)生一個(gè)隨機(jī)數(shù)在C++中,λ表達(dá)式是通過(guò)函數(shù)對(duì)象來(lái)實(shí)現(xiàn)的。對(duì)于下面的λ表達(dá)式: [...](intx)->int{.......}首先,隱式定義一個(gè)類:數(shù)據(jù)成員對(duì)應(yīng)λ表達(dá)式中用到的環(huán)境變量,用構(gòu)造函數(shù)對(duì)它們進(jìn)行初始化。按相應(yīng)λ表達(dá)式的功能重載了函數(shù)調(diào)用操作符。然后,創(chuàng)建上述類的一個(gè)臨時(shí)對(duì)象(設(shè)為obj)最后,在使用上述λ表達(dá)式的地方用該對(duì)象來(lái)替代:作用于實(shí)參進(jìn)行函數(shù)調(diào)用cout<<[...](intx)->int{.......}(3);cout<<obj(3);傳給其它函數(shù)f([...](intx)->int{.......});f(obj);操作符new與delete的重載操作符new和delete用于創(chuàng)建和撤銷(xiāo)動(dòng)態(tài)對(duì)象:A*p=newA;......deletep;操作符new有兩個(gè)功能:為動(dòng)態(tài)對(duì)象分配空間調(diào)用對(duì)象類的構(gòu)造函數(shù)操作符delete也有兩個(gè)功能:調(diào)用對(duì)象類的析構(gòu)函數(shù)釋放動(dòng)態(tài)對(duì)象的空間系統(tǒng)提供的new和delete操作所涉及的空間分配和釋放是通過(guò)系統(tǒng)的堆區(qū)管理系統(tǒng)來(lái)進(jìn)行的,它要考慮各種大小的空間分配與釋放,對(duì)某個(gè)類而言,效率常常不高??梢葬槍?duì)某個(gè)類重載操作符new和delete,使得該類能以自己的方式來(lái)實(shí)現(xiàn)動(dòng)態(tài)對(duì)象空間的分配和釋放功能。注意:重載操作符new和delete時(shí),重載的是它們的分配空間和釋放空間的功能,不影響對(duì)構(gòu)造函數(shù)和析構(gòu)函數(shù)的調(diào)用。重載操作符new操作符new必須作為靜態(tài)的成員函數(shù)來(lái)重載(static說(shuō)明可以不寫(xiě)),其格式為:void*operatornew(size_tsize);
返回類型必須為void*參數(shù)size表示對(duì)象所需空間的大小,其類型為size_t(unsignedint)例:把動(dòng)態(tài)對(duì)象初始化為全‘0’#include<cstring>classA{ intx,y; public: void*operatornew(size_tsize) { void*p=malloc(size);//調(diào)用系統(tǒng)堆空間分配操作。
memset(p,0,size);//把申請(qǐng)到的堆空間初始化為全“0”。
returnp; } ......};上面重載的new與系統(tǒng)提供的差別在于:它可以為一個(gè)沒(méi)有定義任何構(gòu)造函數(shù)的動(dòng)態(tài)對(duì)象提供初始化!重載的new操作符的使用格式與系統(tǒng)提供的基本相同。例如(假設(shè)A中重載了new):A*p=newA;自動(dòng)計(jì)算A的大小,把它作為參數(shù)(size)去調(diào)用new的重載函數(shù)。調(diào)用A類默認(rèn)構(gòu)造函數(shù)。A*q=newA(...);自動(dòng)計(jì)算A的大小,把它作為參數(shù)(size)去調(diào)用new的重載函數(shù)。調(diào)用A類帶參數(shù)(...)的構(gòu)造函數(shù)。重載new時(shí),除了對(duì)象空間大小參數(shù)以外,也可以帶有其它參數(shù),void*operatornew(size_tsize,…);如果重載的new包含其它參數(shù),其使用格式為:p=new(...)A(...);...
表示提供給new重載函數(shù)的其它參數(shù)...
表示提供給A類構(gòu)造函數(shù)的參數(shù)例:在非“堆區(qū)”為動(dòng)態(tài)對(duì)象分配空間#include<cstring>classA{ intx,y; public: A(inti,intj){x=i;y=j;} void*operatornew(size_tsize,void*p) {returnp; }};......charbuf[sizeof(A)];A*p=new(buf)A(1,2);//動(dòng)態(tài)對(duì)象的空間分配為buf......p->~A();//使得p所指向的對(duì)象消亡。不能用系統(tǒng)的delete重載delete一般來(lái)說(shuō),如果對(duì)某個(gè)類重載了操作符new,則相應(yīng)地也要重載操作符delete。操作符delete也必須作為靜態(tài)的成員函數(shù)來(lái)重載(static說(shuō)明可以不寫(xiě)),其格式為:
voidoperatordelete(void*p,size_tsize);返回類型必須為void。第一個(gè)參數(shù)類型為void*,指向?qū)ο蟮膬?nèi)存空間。第二個(gè)參數(shù)可有可無(wú),如果有,則必須是size_t類型。
重載后,操作符delete的使用格式與未重載的相同。classA{intx,y;public:
void*operatornew(size_tsize){void*p=malloc(size);//申請(qǐng)堆空間memset(p,0,size);returnp;}voidoperatordelete(void*p)
{free(p);}......};......A*ptr=newA;......deleteptr;//調(diào)用delete重載函數(shù),把ptr傳給p例:重載操作符new與delete來(lái)管理程序中某類動(dòng)態(tài)對(duì)象的堆空間。
就某一個(gè)類的動(dòng)態(tài)對(duì)象而言,系統(tǒng)的堆空間管理效率不高,系統(tǒng)要考慮程序中各種大小的堆空間申請(qǐng)和釋放問(wèn)題。另外,系統(tǒng)的堆空間管理會(huì)面臨“碎片”問(wèn)題:在下面的情況下,再創(chuàng)建一個(gè)A類對(duì)象,這時(shí),每個(gè)可分配空間都不夠,但可分配空間總和是夠的。CABBCBBC對(duì)于某個(gè)類的動(dòng)態(tài)對(duì)象,它可以自己管理空間的分配和釋放,以提高效率。重載new第一次創(chuàng)建該類的動(dòng)態(tài)對(duì)象時(shí),先從系統(tǒng)管理的堆區(qū)中申請(qǐng)一塊大的空間,然后把上述大空間分成若干小塊,每個(gè)小塊的大小為該類一個(gè)對(duì)象的大小,用鏈表來(lái)管理這些小塊;在上述鏈表中為該類動(dòng)態(tài)對(duì)象分配空間。重載delete該類的一個(gè)動(dòng)態(tài)對(duì)象消亡時(shí),該對(duì)象的空間歸還到new操作中申請(qǐng)到的大空間(鏈表)中,而不是歸還到系統(tǒng)的堆區(qū)中。#include<cstring>classA{ ......//類A的已有成員說(shuō)明。
public: staticvoid*operatornew(size_tsize); staticvoidoperatordelete(void*p); private:
A*next;//用于組織A類對(duì)象自由空間結(jié)點(diǎn)的鏈表。 staticA*p_free;//用于指向A類對(duì)象的自由空間鏈表頭。};A*A::p_free=NULL;constintNUM=32;void*A::operator
new(size_tsize){ if(p_free==NULL) { //申請(qǐng)NUM個(gè)A類對(duì)象的大空間。 p_free=(A*)malloc(size*NUM);//一個(gè)動(dòng)態(tài)數(shù)組 //在大空間上建立自由結(jié)點(diǎn)鏈表。
for(inti=0;i<NUM-1;i++)
p_free[i].next=&p_free[i+1];
p_free[NUM-1].next=NULL; }//從鏈表中給當(dāng)前對(duì)象分配空間 A*p=p_free; p_free=p_free->next; memset(p,0,size);//可由構(gòu)造函數(shù)完成 returnp;}p_free:NULLq1:A*q1=newA;voidA::operatordelete(void*p){ ((A*)p)->next=p_free; p_free=(A*)p;}A*q1=newA;A*q2=newA;deleteq1;p_free:NULLq1q2(p)p_freeNULL在創(chuàng)建動(dòng)態(tài)對(duì)象時(shí),一大塊用完了,怎么辦?將會(huì)申請(qǐng)第二大塊,并再次構(gòu)建鏈表:NULLp_freeNULL經(jīng)過(guò)若干次分配、歸還之后,可能會(huì)出現(xiàn)下面的格局:所有A類對(duì)象消亡后,如何歸還所有的大塊?動(dòng)態(tài)對(duì)象數(shù)組的創(chuàng)建與撤銷(xiāo)A*p=newA[10];...p[0]、p[1]、...、p[9]...delete[]p;//“[]”不能漏掉!上述操作將調(diào)用下面的重載函數(shù)(隱式或自定義):void*operatornew[](size_tsize);voidoperatordelete[](void*p);注意:當(dāng)類(或基類和成員對(duì)象類)中有析構(gòu)函數(shù)時(shí),傳給函數(shù)new[]的參數(shù)size的實(shí)際值會(huì)比對(duì)象數(shù)組需要的空間多4個(gè)字節(jié),用于存儲(chǔ)元素個(gè)數(shù)!例如,假設(shè)類A有析構(gòu)函數(shù),則A*p=newA[10];
//size:sizeof(A)*10+4......delete[]p;//會(huì)根據(jù)存儲(chǔ)的元素個(gè)數(shù)調(diào)用每個(gè)元素的析構(gòu)函數(shù)元素個(gè)數(shù)p自定義類型轉(zhuǎn)換操作符
類中帶一個(gè)參數(shù)的構(gòu)造函數(shù)可以用作從其它類型到該類的轉(zhuǎn)換。例如:classComplex{ doublereal,imag; public: Complex(){real=0;imag=0;}
Complex(doubler){ real=r;imag=0;} Complex(doubler,doublei){real
溫馨提示
- 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ù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度農(nóng)業(yè)科技園區(qū)設(shè)施租賃協(xié)議4篇
- 啟迪未來(lái)點(diǎn)亮夢(mèng)想
- 2025版收入證明模板制作與市場(chǎng)推廣合作合同3篇
- 2025年全球及中國(guó)氣體激光清洗設(shè)備行業(yè)頭部企業(yè)市場(chǎng)占有率及排名調(diào)研報(bào)告
- 2025年全球及中國(guó)住宅用灌溉噴水閥行業(yè)頭部企業(yè)市場(chǎng)占有率及排名調(diào)研報(bào)告
- 2025-2030全球?qū)櫸锔闻K功能補(bǔ)充劑行業(yè)調(diào)研及趨勢(shì)分析報(bào)告
- 2025-2030全球印章套件行業(yè)調(diào)研及趨勢(shì)分析報(bào)告
- 2025-2030全球光伏發(fā)電箱變行業(yè)調(diào)研及趨勢(shì)分析報(bào)告
- 施工承包合同標(biāo)準(zhǔn)模板
- 2025版?zhèn)€人購(gòu)房貸款還款順序合同模板3篇
- 小學(xué)六年級(jí)數(shù)學(xué)上冊(cè)《簡(jiǎn)便計(jì)算》練習(xí)題(310題-附答案)
- 2023-2024學(xué)年度人教版一年級(jí)語(yǔ)文上冊(cè)寒假作業(yè)
- 培訓(xùn)如何上好一堂課
- 高教版2023年中職教科書(shū)《語(yǔ)文》(基礎(chǔ)模塊)下冊(cè)教案全冊(cè)
- 2024醫(yī)療銷(xiāo)售年度計(jì)劃
- 稅務(wù)局個(gè)人所得稅綜合所得匯算清繳
- 人教版語(yǔ)文1-6年級(jí)古詩(shī)詞
- 上學(xué)期高二期末語(yǔ)文試卷(含答案)
- 軟件運(yùn)維考核指標(biāo)
- 空氣動(dòng)力學(xué)仿真技術(shù):格子玻爾茲曼方法(LBM)簡(jiǎn)介
- 對(duì)表達(dá)方式進(jìn)行選擇與運(yùn)用
評(píng)論
0/150
提交評(píng)論