對象模型:關(guān)于vptr(虛指針)和vtbl(虛表)
<big>1. 類里面如果有一個或多個虛函數(shù),就會存在一個虛指針,虛指針指向一個虛表,虛表中為幾個或多個指針块请,指向類的虛函數(shù);
2. 繼承父類的函數(shù)只是繼承函數(shù)的調(diào)用權(quán)拳缠;
3. 調(diào)用虛函數(shù)時先通過虛指針找到虛表墩新,通過虛表中相應(yīng)的指針調(diào)用相應(yīng)的函數(shù);
4. 直接call一個函數(shù)地址來進(jìn)行調(diào)用為靜態(tài)綁定窟坐;
5. 通過指針調(diào)用類的函數(shù)海渊、指針是向上轉(zhuǎn)型即指針為父類類型指針、函數(shù)為虛函數(shù)哲鸳。則調(diào)用為動態(tài)綁定(p->vptr[n])(p)*臣疑。</big>
關(guān)于this指針
<big>1. 所有成員函數(shù)一定會有一個this作為函數(shù)的參數(shù),通過對象調(diào)用成員函數(shù)徙菠,函數(shù)中會自動加入一個當(dāng)前對象的指針this讯沈;
2. 所以派生類調(diào)用基類的函數(shù),函數(shù)中又調(diào)用了一個虛函數(shù)懒豹,由于是派生類的指針?biāo)蕴摵瘮?shù)就會通過this的虛表找到派生類相應(yīng)的函數(shù)實現(xiàn)芙盘;
關(guān)于Dynamic Binding
<big>靜態(tài)綁定在匯編語言中通過call相應(yīng)的函數(shù)指針,而動態(tài)綁定call后面不是一個固定的地址脸秽,而是通過指針找到相應(yīng)的虛指針在找到虛表儒老,通過虛表調(diào)用真正的目標(biāo)函數(shù);
const
<big>
2. 函數(shù)后有或者沒有const是兩個不同的函數(shù)记餐,可以通過const實現(xiàn)函數(shù)重載驮樊;
3. copy on write(COW):通過函數(shù)后面加或者不加const能夠?qū)崿F(xiàn)考慮COW。
New和Delete
<big>new和delete為表達(dá)式片酝,不能進(jìn)行重載囚衔。分解之為調(diào)用operator new和operator delete,這是可以被重載的雕沿,內(nèi)部是通過malloc()和free實現(xiàn)的练湿。
operator new 和operator delete
1. 全局函數(shù)重載::
operator new和operator delete不是由使用著去調(diào)用的,這是由編譯器進(jìn)行調(diào)用审轮。operator new接受大小operator delete接受指針肥哎。影響層面廣泛。
2. 成員重載
可以對有或者沒有[]進(jìn)行重載疾渣。
實例,接口
1. 下圖為強(qiáng)制繞過自己對operator new或operator delete的重載,采用默認(rèn)全局的函數(shù)使用方法达椰。
2. operator new[]與operator new重載時形參是不一樣的呈枉,不帶中括號的為內(nèi)存大小是size_t類型酥泞;帶中括號的形參為個數(shù),執(zhí)行后會調(diào)用這么多次構(gòu)造函數(shù)悯姊。
重載 new(),delete() (placement)
1. 重載之后可以new(......) class_ame這樣調(diào)用辉阶;其中第一參數(shù)必須為size_t垃僚。
2. new的時候調(diào)用構(gòu)造函數(shù)罕袋,構(gòu)造失敗就會調(diào)用相應(yīng)的delete()溅固。
對于operator new和operator delete的理解
1. 由于operator new進(jìn)行重載是有很多不同的方法亮元,之間進(jìn)行區(qū)分的主要是參數(shù)個數(shù)和類型有很大的相關(guān)性,不能搞錯了。
2. operator new和operator delete作為成員函數(shù)重載時成肘,它是個靜態(tài)函數(shù)(static)批销。如果在調(diào)用的時候當(dāng)作普通的成員函數(shù)來調(diào)用就會報錯。
3. 對于operator delete:一般來說operator delete(void)的優(yōu)先級比operator delete(void,size_t)要高骡技,這意味著如果在同一空間(scope)定義了這兩種形式的delete鸣个,擁有單一參數(shù)者優(yōu)先被編譯器選擇(vs**測試)。
關(guān)于作業(yè)
1. 可以得出在堆區(qū)創(chuàng)建一個對象時布朦,首先是調(diào)用operator new分配足夠大的空間囤萤,再調(diào)用構(gòu)造函數(shù)創(chuàng)建一個對象,如果是派生類則先調(diào)用基類的構(gòu)造函數(shù)然后調(diào)用派生類的構(gòu)造函數(shù)是趴。在delete的時候先調(diào)用基類的構(gòu)造函數(shù)涛舍,在調(diào)用派生類的構(gòu)造函數(shù),最后通過operator delete釋放內(nèi)存唆途。
2. 關(guān)于virtual dtor虛析構(gòu)函數(shù)富雅,在本次作業(yè)中我嘗試過用父類的指針創(chuàng)建堆區(qū)子類對象。然后通過delete去釋放內(nèi)存肛搬,反向?qū)τ谧宇惖奈鰳?gòu)函數(shù)根本就沒有被調(diào)用没佑,而且operator delete也是用的全局的哪一個,并沒有使用Apple類重載的温赔,導(dǎo)致delete只是釋放掉了apple對象的基類成員所占的空間蛤奢,造成內(nèi)存泄漏。通過資料發(fā)現(xiàn)這是基類的析構(gòu)函數(shù)沒有加virtual的緣故。所以如果一個類要作為基類來使用啤贩,就必須使用虛析構(gòu)函數(shù)待秃。</big>