c primer中說了,在乙個物件呼叫其成員函式時,它隱含的乙個形參this指標。總結一下如下兩表:例如,我們定義了乙個函式ctest::ttt();實際上在編譯器中該函式的定義就是ctest::ttt(ctest *const
this),該this指標所指向的內容可以改變,但是該this指標不可以被改變。當我們用ctest的乙個物件test1呼叫ttt函式時即test1.ttt()時,編譯器就會將它解釋為ttt(&test1),所以我們在ttt中使用this指標就可以改變物件test1的成員變數了。
但是,當我們的物件是const物件時,即const ctest ttt;這時候表示什麼意思呢,ttt的內容是不可以改邊的,當我們把&ttt作為乙個引數傳到形參this時,矛盾出現了:ttt是乙個常量,其成員不可以被改變;this指標的成員變數是可以改變的。如果我能正確的將ttt的位址傳給this,那麼ttt這個常量的值不是可以在this中被改變了嗎,所以,編譯器是不允許這種情況出現的,就提示錯誤了。故const物件不能訪問非const成員函式。
同理,當我們的成員函式是const成員函式時,例:ctest::ttt() const,在編譯器解釋時會將該函式解釋為ctest::ttt(const ctest * const this),this指標及其所指向的內容都不可以被修改,前面提到的矛盾也就不存在了,所以const物件可以訪問const成員變數。
物件.成員函式
物件成員函式
是否可行
const
const
√const
non-const
錯
non-const
const
√non-const
non-const√
成員函式呼叫成員函式
成員函式
成員函式
是否可行
const
const
√const
non-const
錯
non-const
const
√non-const
non-const
√
class string1
~string1()
operator
char *() const
void getdata() const
// 需要加上const 不然會提示錯誤物件包含與成員函式不相容的型別限定符
private:
char *data;
};
這個時候我們可以
const string1 b("hello");
string1 & alsob=const_cast
(b);
char *str=b;
str[1]='e'; // 這樣就篡改了乙個const物件裡的資料了。。。
b.getdata();
所以我們operator的**需要更改
operator
const
char *() const
這樣我們
const
char *str=b; //只能這樣了。。
//str[1]='e'; //此時就不能更改了
指標並不是返回內部資料控制代碼的唯一途徑。引用也很容易被濫用。下面是一種常見的用法,還是拿 string 類做例子:
class string2
operator
const
char *() const
void getdata() const
// 需要加上const 不然會提示錯誤物件包含與成員函式不相容的型別限定符
char& operator(int index) const
// 不加引用是不能賦值的~
private:
char *data;
};
這樣也可以修改s。。。
const string2 s = "i'm not constant";
s[0]='x';
這類問題的通用解決方案和前面關於指標的討論一樣:或者使函式為非 const,或者重寫函式,使之不返回控制代碼。 並不是只有 const 成員函式需要擔心返回控制代碼的問題,即使是非 const 成 員函式也得承認:控制代碼的合法性失效的時間和它所對應的物件是完全相同的。 這個時間可能比使用者期望的要早很多,特別是當涉及的物件是由編譯器產生的臨時物件時。
所以,對於 const 成員函式來說,返回控制代碼是不明智的,因為它會破壞資料抽象。對於非 const 成員函式來說,返回控制代碼會帶來麻煩,特別是涉及到臨 時物件時。控制代碼就象指標一樣,可以是懸浮(dangle)的。所以一定要象避免 懸浮的指標那樣,盡量避免懸浮的控制代碼。
例如:
string2 some()
......
......
const char *p = some();
cout
char*成員函式將臨時 string 物件轉換為 const char*指標,並用這個指標初始化 pc。 3. 臨時 string
物件被銷毀,其析構函式被呼叫。析構函式中,data 指標被刪除 (**詳見條款 11)。然而,data 和 pc
所指的是同一塊記憶體,所以現在 pc 指 向的是被刪除的記憶體——–其內容是不可確定的。
避免返回內部資料的控制代碼
假設b是乙個const string物件 class string const string b hello world b是乙個const物件 既然b為const,最好的情況當然就是無論現在還是以後,b的值總是 hello world 這就寄希望於別的程式設計師能以合理的方式使用b了。特別是,千萬...
學習 避免返回內部資料的控制代碼
請看物件導向世界裡發生的一幕 物件a 親愛的,永遠別變心!物件b 別擔心,親愛的,我是const。然而,和現實生活中一樣,a會懷疑,能相信b嗎?同樣地,和現實生活中一樣,答案取決於b的本性 其成員函式的組成結構。假設b是乙個const string物件 class string const stri...
條款29 避免返回內部資料的控制代碼
假設b是乙個const string物件 class string const string b hello world b是乙個const物件 看看下面的情形 char str b 呼叫b.operator char strcpy str,hi mom 修改str指向的值 b的值現在還是 hell...