作者littleshan (我要加入劍道社!)
看板C_and_CPP
標題Re: [問題] overloading [] 疑問!!
時間Thu Jul 16 12:30:29 2009
我覺得你的問題在於你可能不太清楚 const member function 的意義。
所謂的 const member function 就是在宣告時於宣告式後加上 const:
class Foo {
public:
void f(); // normal member function
int g() const; // const member function
private:
int data;
};
const member function 的意思是在這個 function 中,並不會去改變
物件中的 member variable(註)。因此若你宣告一個 const Foo 物件,
你不能呼叫 f(),因為 f() 的內部可能會改變 member variable,但
你可以呼叫 g()。
void Foo::f()
{
data = 10; // OK
}
int Foo::g() const
{
data = 10; // 錯誤,g() 是 const member function,不能修改 data
return data; // 這行 OK,因為 return 並不會改變 data 的值
}
void bar()
{
const Foo x;
x.f(); // 錯誤,f() 可能會改變 x 的內容
x.g(); // OK,g() 不會改變 x 的內容
}
回到你的問題,為什麼你要同時提供 const 和 non-const operator[] 呢?
答案是你的物件可能同時在這兩種情況下用到:
void baz(const Array& a) // a 是一個 Array 物件,我們不能改變它的內容
{
cout << a[10]; // OK,因為我們沒有改變 a 的內容
a[10] = 5; // 這行會錯誤,因為我們不能修改 a 的內容
Array b = a; // 複製一份到 b,而且 b 不是 const 物件
b[10] = 5; // OK,我們可以改 b 的內容
}
我們不能單純提供 non-const operator[]
因為當 a 為 const 的時候,他無法呼叫 non-const operator[]
class Array{
public:
int& operator[](int index); // 沒有 const,寫 a[10] 會直接報錯
};
但把它加上 const 就可以了嗎?當然不是:
class Array{
public:
int& operator[](int index) const;
};
若你這樣寫,那麼在 a[10] = 5 這行,compiler 會一聲不吭讓你編過,
於是使用者就發現他上當了:他明明說 a 是 const,但還是改變了 a 的內容!
於是你改成這樣:
class Array{
public:
const int& operator[](int index) const;
// 或是另一個方式,兩者皆可行
// int operator[](int index) const;
};
這麼一來,cout << a[10] 可以編過,但 a[10] = 5 就會產生錯誤了。至於
non-const 物件 b,我們再額外提供 non-const operator[]
// 最終版本
class Array{
public:
const int& operator[](int index) const; // 給 a 用的
int& operator[](int index); // 給 b 用的
};
所以你寫 a[10],會呼叫 const operator[];寫 b[10] 則是呼叫 non-const
operator[]。讓對的寫法過關,不對的寫法產生 compiler error,這是設計
library 時一個重要的概念。
-
註:const member function 無法修改一般的 member variable,但若你在宣
告 member variable 時加上 mutable 關鍵字,就可以打破這項限制。因此,
C++ 的 const member function 提供的是「邏輯上的常數性質」,亦即當
你呼叫 const member function 時,物件的內部資料可能還是有改變,只
是展現在外部的行為上是不變的。
題外話:看一個人懂不懂 C++,從 const 來看還滿準的。會用 const 的人,
多少都有一定的經驗。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 219.87.151.2
※ 編輯: littleshan 來自: 219.87.151.2 (07/16 12:45)
推 cassey:謝謝大大的解釋,關念清楚多了,另:我是新手,被大大說中 07/16 13:15
→ littleshan:會問「為什麼」,是好的開始,加油 07/16 13:33
推 silveriii:推 很清楚 07/16 14:08
推 nickexe:實作上補充,通常你可以只寫 const 版本的實作,然後 07/17 01:43
→ nickexe:non-const 去呼叫 const 版本,可以減少重複的程式碼 07/17 01:44
推 archon:來朝聖的... 好文 <(_ _)> 10/15 22:17