天天看點

第十二章 類 —— 第二節 隐含的this指針和mutable可變資料成員

第十二章 類

關于C++的幾篇部落格,參考人民郵電出版社的《C++ Primer 中文版》一書。

本章節介紹類的隐含this指針和mutable可變資料成員。

第二節 隐含的this指針和mutable可變資料成員

類的成員函數都具有一個附加的隐含形參,就是this指針,它指向所在類對象。

首先上個例子,然後根據例子了解this指針。

// 例1
class Screen {
public:
    typedef std::string::size_type index;
    Screen& move( index r, index c);
    Screen& set( char );
    Screen& display( std::ostream &os ) {
        do_display( os );
        return *this;
    }
    const Screen& display( std::ostream &os ) const {
        do_display( os );
        return *this;
    }
private:
    std::string contents;
    index height;
    index width;
    void do_display( std::ostream &os ) const {
        os << contents;
    }
};

Screen& Screen::set( char c )
{
    contents[cursor] = c;
    return *this;
}
Screen& Screen::move( index r, index c )
{
    index row = r*width;
    cursor = row+c;
    return *this;
}
           

一、必須用this指針的情況:

成員函數可以顯式使用this指針,但不必須。

那麼我們隻需要知道什麼時候必須得用呢?當我們有必須使用指向類對象的指針或引用的理由時,就是必須得用的時候了。

比如,當成員函數的傳回類型是所在類類型的指針或引用,且指向所在的對象時,就必須傳回this了,這樣友善其他成員函數被連續調用,如:

myScreen.move( 4, 0 ).set( '#' ); // move cursor to given position, and set that character

上面的執行語句等價于:

myScreen.move( 4, 0 );

myScreen.set( '#' );

見例1的set和move函數定義部分Line24~34(注意:傳回類型之是以不能設定為Screen而是要設定成Screen&或Screen*,是因為我們上一篇部落格最後提到過的,類定義體内不能定義自身類型的資料成員。)

二、可變資料成員mutable

class Screen {

private:

    mutable int access_str;

}

我們有時希望類的資料成員是可以被改變的,那麼定義時類型名前加mutable關鍵字就可以定義類的可變資料成員。

這樣,mutable資料成員永遠都不能為const,即便是在const成員函數中,甚至當它是const對象的成員時,都可以被修改。

三、const成員函數及this指針

1、如果在非const成員函數中,傳回this指針,則this所指向的對象可以被改變,但this儲存的位址不可修改(當然了,這是指針的屬性)。

2、如果在const成員函數中,傳回this指針,則this所指向的對象内容不可修改,且this儲存的位址也不可改,那麼也就是說this指向的是一個const對象。

綜上,const成員函數隻能傳回const的this指針。

3、那麼,這樣就存在一個問題,如果我想在調用const成員函數傳回的指針上,繼續做修改資料成員的操作,那麼就是不可實作的了。

要解決這個問題,自然就想到函數的重載了。

4、const成員函數的重載

const成員函數的重載,請參看本章節例1的Line7~14。

重載以後,const的Screen對象将會自動調用const的成員函數display;非const的對象兩種成員函數都可以使用,當然最好是用非const的。

// 例2
Screen myScreen;
const Screen blank;
myScreen.display(cout);                // 調用非const的display函數
myScreen.set('#').display(cout);   // 調用非const的display函數
blank.display(cout);                        // 調用const的display函數