從一個C++菜鳥改函數開始
1 CString MyClass::GetStringValue() const 2 { 3 return m_strValue; 4 }
這個值可能還沒有賦值,好吧,那麼我先判斷是不是為空,為空就賦值了
CString MyClass::GetStringValue() const { if(m_strValue.IsEmpty()) SetStringValue(); return m_strValue; }
結果,編譯就不過,因為有個規則:const函數裡面不能調用非const函數。
看到下面的編譯錯誤:
error C2662: “MyClass::SetStringValue”: 不能將“this”指針從“const MyClass”轉換為“MyClass &”
嘿嘿原來是這樣:當我們定義了一個類的成員函數會默認傳進來一個this指針,但是如果是一個const 函數那麼是不是就傳竟來一個const的指針呢?所以我想編譯器看到是這樣的:
CString MyClass::GetStringValue(const MyClass* this) { if(this->m_strValue.IsEmpty()) this->SetStringValue(); return this->GetStringValue(); }
後來驗證一下,創建了一個static函數模擬一下:
CString MyClass::GetStringValueS(const MyClass* mcp) { if(mcp->m_strValue.IsEmpty()) mcp->SetStringValue(); return mcp->GetStringValue(); }
編譯真的得到一個同樣的錯誤:
error C2662: “MyClass::SetStringValue”: 不能將“this”指針從“const MyClass”轉換為“MyClass &”
所以我試著去打破const規則:
CString MyClass::GetStringValue()const { MyClass * nonconstthis = (MyClass *)this; if(m_strValue.IsEmpty()) nonconstthis->SetStringValue(); return m_strValue; }
結果編譯通過,執行也沒有問題。
所以有一個轉換const_cast<>專門來做這樣的事情:
CString MyClass::GetStringValue()const { if(m_strValue.IsEmpty()) const_cast<MyClass *>(this)->SetStringValue(); return m_strValue; }
最後,我認為,這樣違背了const設計的初衷,這樣對於調用者是一種欺騙(違背契約:我保證不改你),所以不推薦這樣使用。