C++中的const成員函數(函數聲明後加const,或稱常量成員函數)用法詳解

  http://blog.csdn.net/gmstart/article/details/7046140緩存

在C++的類定義裏面,能夠看到相似下面的定義:函數

01 class List {
02 private:
03      Node * p_head;
04      int length;
05      ……
06 Public:
07      int GetLength () const;
08      bool GetNodeInfo(const int index,Node & buffer) const {…… }
09      bool DeleteNode(const int index);
10      …………
11 }

能夠看到,在GetLength和GetNodeInfo兩個成員函數的參數列表後面出現了一個const。這個const指明瞭這個函數不會修改該類的任何成員數據的值,稱爲常量成員函數。
對於const函數的外部定義,也不能忘記書寫const限定符,以下面給出GetLength函數(指返回鏈表的長度)的定義:spa

1 int List::GetLength() const //這裏依然不能忘記const
2 {
3      Return length;
4 }

若是在const成員函數的定義中出現了任何修改對象成員數據的現象,都會在編譯時被檢查出來,如:.net

1 int List::GetLength() const
2 {
3      Return length++; //錯誤!
4 }

const成員函數存在的意義在於它能被const常對象調用。咱們都知道,在定義一個對象或者一個變量時,若是在類型前加一個const,如const int x;,則表示定義的量爲一個常量,它的值不能被修改。可是建立的對象卻能夠調用成員函數,調用的成員函數頗有可能改變對象的值,好比下面這段程序:code

1 const List myList;
2 myList.DeleteNode(3); //錯誤,DeleteLength是非const成員函數

顯然調用DeleteNode這個成員函數刪除一個鏈表結點後,頗有可能改變對象中length(鏈表長度)這個值,這不符合const對象的規定。可是,若是不容許const對象調用任何成員函數又是很是不合理的。因而,咱們把那些確定不會修改對象的各個屬性值的成員函數加上const說明符,這樣,在編譯時,編譯器將對這些const成員函數進行檢查,若是確實沒有修改對象值的行爲,則檢驗經過。之後,若是一個const常對象調用這些const成員函數的時候,編譯器將會容許。好比:orm

1 const List myList;
2 myList.GetLength(); //正確,GetLength是const常函數,它返回鏈表長度,的確沒有改變
3 //屬性值的行爲,被檢驗經過

你可能會問,爲何不在一個const常對象調用成員函數的時候再進行檢查呢?若是被調用的函數會改變對象的屬性值,則當即打住就是了。這樣就不用麻煩地在成員函數後面加const限定符了。然而,這無疑會大大增長編譯時間。考慮下面這段代碼:對象

1 const List MyList;
2 MyList.GetLength();
3 ……
4 MyList.GetLength();
5 ……

這段代碼中,GetLength被調用了兩次,可是編譯時卻也要檢查兩次,倘使一個成員函數被調用屢次,那麼他將在每次調用的時候都會被檢查。這顯然大大不利。而若是在定義類的時候加上const限定符對常函數加以標記,那麼編譯器只是檢查一次就好,在const對象調用成員函數時,const函數將會被直接放行。因此,C++採起了const限定符描述常函數方案而擯棄了後者。因此,即便一個函數沒有修改對象值的行爲,若是沒有加上const限定符說明是常函數,那麼const對象依然不能調用它。
然而,有些時候,咱們卻必需要讓const函數具備修改某個成員數據值的能力。好比一些內部的狀態量,對外部用戶無所謂,可是對整個對象的運行卻大有用處,如支持緩存的技術。遇到這種問題,咱們能夠把一個成員數據定義爲mutable(多變的),它表示這個成員變量能夠被const成員函數修改卻不違法。好比下面定義了一個is_valid類成員:blog

01 class List
02 {
03 private:
04      ……
05      mutable bool is_valid;
06      ……
07 public:
08       bool CheckList() const
09      {
10           if(length >= 1) then return is_valid =true;
11           else return is_valid = false//正確!
12       };

這樣,即便像CheckList這樣的const成員函數修改它也是合法的。
但須要注意的時,不可濫用mutabe描述符,若是在某個類中只有少數一部分是被容許const常量函數修改的,使用mutable是再合適不過的。若是大部分數據都定義爲mutable,那麼最好將這些須要修改的數據放入另外一個獨立的對象裏,並間接地訪問它。ip

相關文章
相關標籤/搜索