this指標和 *this
阿新 • • 發佈:2019-01-05
我們都知道,類的成員函式有一個附加的隱形形參,即指向該類物件的this指標,它與呼叫成員函式的物件繫結在一起。那麼,這個this指標究竟是什麼樣的指標呢?其解引用*this返回的又是怎樣的一個物件呢?
首先,我們以《C++ Primer》書中的Screen類為例說明,這個類只是簡單宣告,有些成員函式的具體實現沒有定義。不必關注成員函式的實現,只需要看它的形式即可。
//定義一個名為Screen的型別來表示計算機上的視窗 #include <iostream> #include <string> using namespace std; class Screen { public: //使用類型別名來簡化類 typedef string::size_type index; //建構函式 Screen(index hght,index wdth,const string &cntnts=""): height(hght),width(wdth),cursor(0),contents(cntnts){} //返回游標的位置 index get_cursor() const{return cursor;}; //增加三個成員函式,返回*this Screen& move(index r,index c);//給定兩個index值,將游標移至新位置 Screen& set(char);//將特定字元設定為特定值 const Screen& display(ostream &os) const;//輸出內容 private: std::string contents;//視窗內容 index cursor;//游標當前停留的位置 index height,width;//視窗的高度和寬度 }; //給定兩個index值,將游標移至新位置 Screen& Screen::move(index r,index c) { index row=r*width; cursor=row+c; return *this; } //將特定字元或游標指向的字元設定為特定值 Screen& Screen::set(char c) { contents[cursor]=c; return *this; } //輸出內容 const Screen& Screen::display(ostream &os) const { os<<contents; return *this; } int main() { //根據螢幕的高度、寬度和內容的值來建立Screen Screen myscreen(5,6,"abcde\nfghij\nklmno\pqrst\nuvwxy"); myscreen.move(4,0).set('#').display(cout); cout<<endl; return 0; }
基本概念
- const指標——指標本身的值不可修改,只能指向指定位置的物件
其定義如下:
int errNumb = 0;
int *const curErr=&errNumb;//curErr是一個指向int型物件的const指標
可以改變const指標所指向的值,但不能改變const指標所儲存的地址,如下:
*curErr=1;//curErr所指向的值變為1,即errNumb=1
++curErr;//錯誤,curErr是一個常量,不能改變
const指標在定義時必須初始化,一經初始化,則指標本身不可再修改,只能指向初始化時的物件。- 指向const物件的指標——只能讀取物件,不能利用指標修改物件
其定義如下:
const double pi = 3.14;
const double *cptr = π//cptr是一個指向const物件pi的指標
*cptr=3.15; //錯誤,不能通過指向常物件的指標修改物件
++cptr;//正確,指向常物件的指標可以指向別處- 常(const)成員函式
在形參表後用const修飾的成員函式,表示只能讀取類的資料成員,不能修改。如上例中的index get_cursor()const{return cursor;};- 常(const)物件
在定義類物件時用const修飾的物件,常物件只能呼叫類中的常成員函式,而普通的物件則沒有此限制。如下例:
const Screen herscreen();//herscreen就是一個Screen型別的常物件
this指標
- this指標是指向類型別的const指標
呼叫成員函式時,隱藏的this指標被初始化為呼叫成員函式的物件的地址,可以改變this所指向的值,但不能改變this所儲存的地址,即this指標只能指向該物件,不能指向別的物件。所以,無論在非const成員函式還是const成員函式中,this首先是一個指向類型別的const指標。在上例中,非const函式Screen& move(index r,index c)的this型別如下:
Screen *const - const成員函式中的this指標——指向常(const)物件的const指標
在普通的非const成員函式中,this的型別就是一個指向類型別的const指標。
而在const成員函式中,因為不能通過this指標修改類的資料成員,只能讀資料成員,故this的型別是一個指向常(const)類物件的const指標。既不能改變this所指向的物件,也不能改變this所儲存的地址。在上例中,const成員函式 get_cursor() const的this的型別如下:
const Screen *const this
返回*this——返回的是一個物件的引用
- 何時返回*this
當我們需要將一個物件作為整體引用而不是引用物件的一個成員是。最常見的情況就是在這樣的函式中返回*this:
該函式返回對呼叫該函式的物件的引用。
如上例中的
myscreen.move(4,0).set('#');
等價於
myscreen.move(4,0);
myscreen.set('#'); - 返回的物件引用是什麼型別:常物件引用 or not?
在普通的非const成員函式中,*this返回的普通的物件引用。在上例中,非const成員函式move( )返回的就是一個普通的物件引用://給定兩個index值,將游標移至新位置 Screen& Screen::move(index r,index c) { index row=r*width; cursor=row+c; return *this; }
而在const成員函式中,*this返回的是常(const)物件引用。在上例中,const成員函式display() const返回的就是一個常(const)物件的引用:
注意://輸出內容 const Screen& Screen::display(ostream &os) const { os<<contents; return *this; }
不能從const成員函式返回指向類物件的普通引用,而應該是const引用。const成員函式只能返回*this作為一個const引用。
Screen& display(ostream &os) const; //錯誤,const成員函式返回的應該是一個const物件引用
const Screen& display(ostream &os) const; //正確
那麼返回型別之間的區別又會導致什麼結果呢?
我們知道,常(const)物件只能呼叫const成員函式,而普通物件既能呼叫const成員函式,又能呼叫非const成員函式。所以,我們可以判斷以下呼叫是否正確?
mysceen.move(4,0).set('#'); //正確,因為非const成員函式move()返回的是普通引用,可以呼叫一切成員函式
myscreen.move(4,0).display(cout);//正確
myscreen.display(cout).set('#'); //錯誤,因為const成員函式display()返回的常物件引用,只能呼叫const成員函式,而set.()是非const成員函式
因此,我們可以確定,返回型別的不同對呼叫成員函式有了限制。
- 非const成員函式的this是一個指向類型別的const指標,可以改變this所指向的值,但不能改變this所儲存的地址,即不能再指向別的物件。
const成員函式的this是一個指向常(const)類物件的const指標,既不能改變this所指向的物件的值,也不能改變this所儲存的地址。 - 非const成員函式的*this返回的是普通引用,可以呼叫一切成員函式。
const成員函式的*this返回的是常(const)物件引用,只能呼叫const成員函式。