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

類定義裏面,可以看到類似下面的定義:

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函數(指返回鏈表的長度)的定義:

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

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

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

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

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

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

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類成員:

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,那麼最好將這些需要修改的數據放入另一個獨立的對象裏,並間接地訪問它。

參考資料:《C++ Programming Language 第三版》
注:本文屬知無涯原創,轉載請註明出處!

發佈了0 篇原創文章 · 獲贊 2 · 訪問量 5977
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章