C++ 之 常量成員函數


  常量成員函數 (const member function), 可讀取類中的數據成員,但不能修改

1  聲明

1.1  const 關鍵字  

  參數列表后,加 const 關鍵字,聲明為常量成員函數,表明其不被允許修改類的數據成員

  下面的類,以年、月、日的形式來表示日期 (注意:年月日的聲明順序)

class Date {
public:
    int GetYear() const { return y_; }int GetMonth() const { return m_; }
    int GetDay() const { return d_; }
    void AddYear(int n); // add n years
private:
    int y_, m_, d_;  
};

  1) 如果常量成員函數,企圖修改類的數據成員,則編譯器會報錯

// error : attempt to change member value in const function
int Date::GetYear() const
{
    return ++y_; 
}

  2) 如果在類外面,“定義” 常量成員函數 ( “定義” = 實現,即 implementation),則 const 關鍵字不可省略

// error : const missing in member function type
int Date::GetYear() 
{
    return y_;
}

1.2  C++ 陷阱

  類中成員變量的聲明順序,決定了成員變量的初始化順序。假設 Date 類中的構造函數為:

public:
    Date() : y_(2016), m_(9), d_(22) {}

  此時,類中的成員函數,在類中的聲明順序 = 構造函數初始化列表順序,故 y_, m_, d_ 都能被順利的初始化為對應的值。

  而當成員變量,在類中的聲明順序 ≠ 構造函數初始化列表順序 時,

public:
    Date() : y_(2016), d_(22), m_(d_-13) {}

  根據成員變量的聲明順序,y_ 首先被初始化為 2016,然后再初始化 m_,但由於 d_ 並未被初始化,所以 m_ 的值是隨機的,最后初始化 d_ 為 22

  這是因為,類的成員變量在初始化時,其初始化的順序只與聲明順序有關,而與在初始化列表中的順序無關。

 

2  調用

  一個常量成員函數,可以被 const 和 non-const 類對象調用; 而非常量成員函數,例如 AddYear(),則只能被 non-const 型類對象調用。

void  Date::AddYear(int n)
{
    y_ += n;  
}

  調用函數如下:

void f(Date& d, const Date& cd)
{
    int i = d.GetYear();    // OK
    d.AddYear(1);        // OK
int j = cd.GetYear(); // OK cd.AddYear(1); // error }

  此時,const 修飾函數形參,是 “接口” 的常用指定形式, 這樣 數據 可以傳遞給 函數 而 本身不被修改

  C++ 中的類型轉換 const_cast,可以移除對象的 const 屬性,具體使用為: const_cast<T>(expression)

  則上例中,要使 const 型類對象,調用類的 non-const 成員函數,可修改代碼如下:

void f(Date& d, const Date& cd)
{
    int j = cd.GetYear();    // OK
    const_cast<Date&>(cd).AddYear(1); 
}

  這種做法雖然是可以的,但它破壞了使用 const 來指定 “接口“ 的本意,並不推薦。


3  解釋

  this 指針 默認是指向 non-const 型類對象的 const 型,因此,不能將 this 指針和 const 型類對象綁定,即 const 類對象無法調用類的成員函數

// 默認的 this 指針,指向 non-const 類對象
Date * const this;

   在成員函數聲明的參數列表后加 const 后綴,表明其 this 指針指向 const 型類對象,如此, const 型類對象便可以調用常量成員函數了

// 常量成員函數中的 this 指針,指向 const 類對象
const Date * const this;

  

小結:

1) 類成員函數聲明中的 const 后綴,表明其 this 指針指向 const 型類對象,因此該 const 類對象,可以調用常量成員函數 (const member function)

2) 一個成員函數,如果對數據成員只涉及讀操作,而不進行修改操作,則盡可能聲明為常量成員函數

 

參考資料:

 <C++ Programming Language_4th> ch 16.2.9.1

 <C++ Primer_5th> ch 7.1.2

 <Effective C++_3rd> Item 3, item 27

 <More Effective C++> Item 2

 <劍指 offer> 第 7 章

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM