C++this指针详解
我們知道在如下例子中。
class Test { public:Fun(int a){//doSomething} private:int a; }; Fun(int a)是Test的非靜態(tài)成員函數(shù),所以編譯器在編譯期間改寫該函數(shù)時(shí),會(huì)自動(dòng)將一個(gè)名為this的指針當(dāng)作為第一個(gè)參數(shù)傳入。類似于:Fun(Test* const this,int a);
那么問題來了,我們理解這個(gè)this指針呢?它有哪些用法和限制呢?
本文試圖通過如下幾個(gè)模塊循環(huán)漸進(jìn)的解析this指針,爭取達(dá)到深入淺出的效果。
1,this指針是什么?
2,this指針的六大屬性。
3,this指針的一些用法。
4,this指針的注意事項(xiàng)。
1,this指針是什么?
關(guān)于this指針超級(jí)經(jīng)典的一段話:
當(dāng)你進(jìn)入一個(gè)房子后,
你可以看見桌子、椅子、地板等,
但是房子你是看不到全貌了。
對(duì)于一個(gè)類的實(shí)例來說,
你可以看到它的成員函數(shù)、成員變量,
但是實(shí)例本身呢?
this是一個(gè)指針,它時(shí)時(shí)刻刻指向你這個(gè)實(shí)例本身。
2,this指針的六大屬性。
我一直都認(rèn)為若想對(duì)某一變量有個(gè)準(zhǔn)確的認(rèn)知,就必須了解其六大屬性。(我的以前博客中有所介紹點(diǎn)擊打開鏈接)
這些屬性是我們對(duì)于this指針應(yīng)該以何種方式正確使用的基礎(chǔ)。
(1)名稱屬性:標(biāo)識(shí)符this表示。
(2)類型屬性:類類型* const(類似于類引用的類型)
(3)值屬性:表示當(dāng)前調(diào)用該函數(shù)對(duì)象的首地址。
(4)作用域:this指針是編譯器默認(rèn)傳給類中非靜態(tài)函數(shù)的隱含形參,所以其作用域在非靜態(tài)成員函數(shù)的函數(shù)體內(nèi)。
(5)鏈接屬性:在該類作用域中,不同類的非靜態(tài)成員函數(shù)中,this這個(gè)指針變量的鏈接屬性是內(nèi)部的,但其所指對(duì)象是外部的,即this變量是不同的實(shí)體,但指向?qū)ο笫峭粋€(gè)。
(6)存儲(chǔ)類型:this指針是由編譯器生成,當(dāng)類的非靜態(tài)成員函數(shù)的參數(shù)個(gè)數(shù)一定時(shí),this指針存儲(chǔ)在ecx寄存器中;若該函數(shù)參數(shù)個(gè)數(shù)未定(可變參數(shù)函數(shù)),則存放在棧中。
3,this指針的一些用法。
(1)作為當(dāng)前類的指針,用來區(qū)別形參和成員變量名稱相同的情況。
比如本文開頭的例子,在Test::Test(int a)函數(shù)的作用域中,形參a與類的成員變量a同名,則形參a會(huì)將成員變量a隱藏。
我們無法直接訪問成員變量a,除了在a前面加上類的名字如Test::a來表示類Test的成員變量a外,
還可以顯示使用this指針來強(qiáng)制訪問對(duì)象成員this->a
(2)this作為返回值,返回當(dāng)前對(duì)象的引用。
在賦值運(yùn)算符重載函數(shù)中,為了不減少賦值運(yùn)算符的功能,我們需要返回一個(gè)引用,來支持重復(fù)賦值(例如a = b =c;)
同樣,在類的賦值運(yùn)算符重載函數(shù)中,我們可以一般使用(*this)作為當(dāng)前對(duì)象返回。
4,this指針的注意事項(xiàng)。
(1)this指針不能為空。
因?yàn)閠his指向一個(gè)已存在的類的實(shí)例對(duì)象,可以通過"->"的方式,訪問類中成員,左移this為空是非法的。
例如,在本文開頭例子中,將成員變量a的訪問權(quán)限改寫為public,然后執(zhí)行下面代碼,雖然編譯會(huì)通過,但程序運(yùn)行會(huì)崩潰。
Test* pT = NULL;pT->a = 10; (2)為什么使用的是指針,而不是引用。this指針的類型和類引用的類型都是Test* const但是,由于歷史原因,C++最初是沒有引用,而有指針的,在設(shè)計(jì)類時(shí),就采用了指針的方式,就導(dǎo)致了現(xiàn)在的局面。雖然引用理論上也可以實(shí)現(xiàn)this的功能。
(3)this指針并不是對(duì)象的一部分,不影響sizeof的結(jié)果。
(4)this指針是由編譯器自動(dòng)生成,作為函數(shù)的第一個(gè)參數(shù),用戶不能顯示傳遞。
(5)this指針不能在構(gòu)造函數(shù)的初始化列表中給對(duì)象的成員變量賦值,
初始化列表本義是在創(chuàng)建類的實(shí)例對(duì)象時(shí),給其中成員變量賦初值。即此時(shí)對(duì)象還未創(chuàng)建完畢。而this指針是類在創(chuàng)建之后,由編譯器自動(dòng)生成的指針,指向?qū)ο蟮氖椎刂贰:唵蝸碚f,先有對(duì)象,后有this指針。所以this指針不能在初始化列表中給成員指針賦初值。
(6)關(guān)于this的存儲(chǔ)及傳參順序
當(dāng)類的非靜態(tài)成員函數(shù)的參數(shù)個(gè)數(shù)是一定時(shí),this指針存儲(chǔ)在ecx寄存器上,通過ecx傳遞給調(diào)用者,此時(shí)函數(shù)調(diào)用約定是_thiscall。若參數(shù)個(gè)數(shù)不確定(可變參數(shù))時(shí),則借助棧,在所有的參數(shù)被壓棧后,再壓入棧中,此時(shí)函數(shù)調(diào)用約定是_cdecl。
示例:將Test類簡化,只聲明,不定義。(可以方便的觀察函數(shù)的調(diào)用約定和函數(shù)名的改寫)
class Test { public:void Fun(int a); };其中,Fun(int a)的個(gè)數(shù)確定,只有一個(gè)。則鏈接時(shí)會(huì)報(bào)錯(cuò): error LNK2019: 無法解析的外部符號(hào) "public: void __thiscall Test::Fun(int)" (?Fun@Test@@QAEXH@Z),該符號(hào)在函數(shù) _main 中被引用將void Fun(int a);改為 void Fun(...);則鏈接時(shí)報(bào)錯(cuò)為: error LNK2019: 無法解析的外部符號(hào) "public: void __cdecl Test::Fun(...)" (?Fun@Test@@QAAXZZ),該符號(hào)在函數(shù) _main 中被引用可以證明,當(dāng)函數(shù)參數(shù)不同時(shí),函數(shù)的調(diào)用約定不同,this的存儲(chǔ)類型不同,造成了其傳參順序的不同。總結(jié)
以上是生活随笔為你收集整理的C++this指针详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mongo vue 破解
- 下一篇: s3c2440移植MQTT