從一個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設計的初衷,這樣對於調用者是一種欺騙(違背契約:我保證不改你),所以不推薦這樣使用。