c 避免返回內部資料的控制代碼

2021-07-10 09:40:48 字數 2881 閱讀 4097

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...