用 const 限定類的成員函數

主的這篇文章值得仔細閱讀。但是,我覺得上述“const 限定類的成員函數”這一部分寫得比較簡略,特別是其中“注意”後面的文字,更是使人不知所云,所以想對這一部分做一些補充說明。

類的成員函數後面加 const,表明這個函數不會對這個類對象的數據成員(準確地說是非靜態數據成員)作任何改變。

在設計類的時候,一個原則就是對於不改變數據成員的成員函數都要在後面加 const,而對於改變數據成員的成員函數不能加 const。所以 const 關鍵字對成員函數的行爲作了更加明確的限定:有 const 修飾的成員函數(指 const 放在函數參數表的後面,而不是在函數前面或者參數表內),只能讀取數據成員,不能改變數據成員;沒有 const 修飾的成員函數,對數據成員則是可讀可寫的。

除此之外,在類的成員函數後面加 const 還有什麼好處呢?樓主告訴我們的:“獲得能力:可以操作常量對象”,其實應該是常量(即 const)對象可以調用 const 成員函數,而不能調用非const修飾的函數。正如非const類型的數據可以給const類型的變量賦值一樣,反之則不成立。

對於const成員函數,"不能修改類的數據成員,不能在函數中調用其他不是const的函數",這是由const的屬性決定的,樓主說得完全正確。

請看下面一個完整的例子,然後我再作一些說明。
 

  1. #include <iostream>;
     
  2. #include <string>;
     
  3. using namespace std;
     

  4.  
  5. class Student {
     
  6. public:
     
  7.   Student() {}
     
  8.   Student( const string& nm, int sc = 0 )
     
  9.     : name( nm ), score( sc ) {}
     

  10.  
  11.   void set_student( const string& nm, int sc = 0 )
     
  12.   {
     
  13.     name = nm;
     
  14.     score = sc;
     
  15.   }
     

  16.  
  17.   const string& get_name() const
     
  18.   {
     
  19.     return name;
     
  20.   }
     

  21.  
  22.   int get_score() const
     
  23.   {
     
  24.     return score;
     
  25.   }
     

  26.  
  27. private:
     
  28.   string name;
     
  29.   int score;
     
  30. };
     

  31.  
  32. // output student's name and score
     
  33. void output_student( const Student& student )
     
  34. {
     
  35.   cout << student.get_name() << "\t";
     
  36.   cout << student.get_score() << endl;
     
  37. }
     

  38.  
  39. int main()
     
  40. {
     
  41.   Student stu( "Wang", 85 );
     
  42.   output_student( stu );
     
  43. }
複製代碼



設計了一個類 Student,數據成員有 name 和 score,有兩個構造函數,有一個設置成員數據函數 set_student(),各有一個取得 name 和 score 的函數 get_name() 和 get_score()。請注意 get_name() 和 get_score() 後面都加了 const,而 set_student() 後面沒有(也不能有const)。

首先說一點題外話,爲什麼 get_name() 前面也加 const。如果沒有前後兩個 const 的話,get_name() 返回的是對私有數據成員 name 的引用,所以通過這個引用可以改變私有成員 name 的值,如
 

  1.   Student stu( "Wang", 85 );
     
  2.   stu.get_name() = "Li";
複製代碼


即把 name 由原來的 "Wang" 變成了 "Li",而這不是我們希望的發生的。所以在 get_name() 前面加 const 避免這種情況的發生。

那麼,get_name() 和 get_score() 這兩個後面應該加 const的成員函數,如果沒有 const 修飾的話可不可以呢?回答是可以!但是這樣做的代價是:const對象將不能再調用這兩個非const成員函數了。如
 

  1. const string& get_name(); // 這兩個函數都應該設成 const 型
     
  2. int get_score();
     
  3. void output_student( const Student& student )
     
  4. {
     
  5.   cout << student.get_name() << "\t"; // 如果 get_name() 和 get_score() 是非const成員函數,這一句和下一句調用是錯誤的
     
  6.   cout << student.get_score() << endl;
     
  7. }
複製代碼


由於參數student表示的是一個對const Student型對象的引用,所以 student 不能調用非const成員函數如 set_student()。如果 get_name() 和 get_score() 成員函數也變成非const型,那麼上面的 student.get_name() 和 student.get_score() 的使用就是非法的,這樣就會給我們處理問題造成困難。

因此,我們沒有理由反對使用const,該加const時就應該加上const,這樣使成員函數除了非const的對象之外,const對象也能夠調用它。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章