轉載:http://www.cnblogs.com/little-sjq/p/9fed5450f45316cf35f4b1c17f2f6361.html
C++ Primer 第07章 類
7.1.2
Sales_data類的定義如下:
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
#include <iostream>
class Sales_data {
public:
std::string isbn() const {return bookNo;}
Sales_data& combine(const Sales_data&);
double avg_price() const;
private:
- std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
Sales_data add(const Sales_data&, const Sales_data&);
std::ostream &print(std::ostream&, const Sales_data&);
std::istream &read(std::istream&, const Sales_data&);
#endif
注意第8行:
std::string isbn() const {return bookNo;}
這里const的作用是修改隱式this指針的類型,默認情況下,this的類型是指向類類型非常量版本的常量指針。例如在Sales_data成員函數中,this的類型是Sales_data *const,即類一旦實例化一個對象后,this指向這個對象,是不能改變的,但是對象本身可以變(通俗的講,this保存的地址不能變,但是*this指向的內容是可以變的,所以*this是非常量,不可以將this綁定一個常量對象),舉個例子:
const int a = 5; //a為整型常量
int *const pa = &a; //pa是常量指針,但是*pa可以變,但是a又是常量,所以報錯
所以這樣就會帶來一個問題:我們不能在一個常量對象上調用普通成員函數,測試如下:
去掉const,測試代碼如下:
#include "Sales_data.h"
int main()
{
Sales_data data1;
std::cout << data1.isbn() << std::endl;
return 0;
}
結果OK,data1是非常量,調用普通成員函數沒有問題,下面做一個改變,將data1聲明成常量
#include "Sales_data.h"
int main()
{
const Sales_data data1;
std::cout << data1.isbn() << std::endl;
return 0;
}
CodeBlocks編譯報錯
error: passing 'const Sales_data' as 'this' argument of 'std::string Sales_data::isbn()' discards qualifiers [-fpermissive]
如果isbn是一個普通函數而this是一個普通指針參數,則我們應該把this聲明成const Sales_data *const。畢竟,在isbn的函數體內不會改變this所指向的對象,所以把this設置為指向常量的指針有助於提高函數的靈活性。
然而,this是隱式的並且不會出現在參數列表中,所以在哪兒將this聲明成指向常量的指針就成為我們必須面對的問題。C++語言的做法是允許把const關鍵字放在成員函數的參數列表之后,此時,緊跟在參數列表后面的const表示this是一個指向常量的指針。像這樣使用const的成員函數被稱作常量成員函數(const member function)。
可以把isbn的函數體想象成如下形式:
//偽代碼,說明隱式的this指針是如何使用的
//下面的代碼是非法的:因為我們不能顯示地定義自己的this指針
//謹記此處的this是一個指向常量的指針,因為isbn是一個常量成員
std::string Sales_data::isbn(const Sales_data *const this)
{ return this->isbn; }
因為this是指向常量的指針,所以常量成員函數不能改變調用它的對象的內容。在上例中,isbn可以讀取調用它的對象的數據成員,但是不能寫入新值。
note:常量對象,以及常量對象的引用或指針都只能調用常量成員函數。