2013-10-17 31 views
1

我繼承了MFC類CString的(沒有錯類,但請相信我,我需要做的時這對於具體的實現)。我成功地定製了一些行爲,但我注意到我丟失了隱式(LPCTSTR)運算符,這似乎是在將CString傳遞給格式字符串時發生的。無論是CString :: Format還是prinf/sprintf,都會發生這種奇蹟。例如:子類MFC的CString,失去隱式轉換的CString傳遞給格式字符串(的sprintf,CString的:: formatString的,等等)

CString Str = _T("Really cool string"); 
TCHAR szBuffer[32]; 
_stprintf(szBuffer, _T("Here it is: %s"), Str); 

我還沒有想出這種神奇的是如何與一個標準的CString的工作,因爲CString的:: formatString的只是傳遞變量參數列表通過對_vswprintf和_swprintf。但無論它在我的派生類中是否缺失。

操作(LPCTSTR)如預期的繼承,並明確工作時調用。

任何想法?

回答

2

您的假設是錯誤的:當CString對象傳遞給printf樣式函數時,沒有隱式轉換爲LPCTSTR。編譯器無法知道這就是你想要的 - 它不會解析格式字符串來推斷類型信息。

取而代之,您的CString對象被傳遞到printf,與一樣。這裏神奇的是,在CString作者預測何時以及如何隱式轉換操作符被調用有關錯誤的假設和模型CString可與C-字符串是兼容的。要這樣做,CString包含一個LPTSTR指針和沒有v表。現在,如果CString對象被傳遞給printf風格的函數,則只有該指針會作爲參數結束,並且所有內容都可以正常工作。請注意,看起來工作是一種未定義行爲的有效形式。這未定義的行爲。

如果你想知道在哪裏CString存儲剩餘信息(電流的大小,容量等),它駐留在內存中僅領先字符緩衝區的。這樣,所有的信息都可以通過一個單一的指針:

CStringData* GetData() const throw() { 
    return(reinterpret_cast< CStringData* >(m_pszData)-1); 
} 

我們解決您的實際問題:不要依賴未定義行爲,使用顯式強制在必要時,沒有人會受到傷害:

_stprintf(szBuffer, _T("Here it is: %s"), static_cast<LPCTSTR>(Str)); 

作爲替代演員,你可以撥打CString::GetString()

_stprintf(szBuffer, _T("Here it is: %s"), Str.GetString()); 

還要記住:從類派生不提供虛擬析構函數是等待發生的資源泄漏。換句話說:不要從CString派生。

+0

或者使用功能的CString :: GetString的 – xMRi

+0

@xMRi這是真的。我更新了答案。 – IInspectable

0

當你從一個類繼承,並不是所有的運營商都繼承。 Google是C++中運算符繼承的主題。在您的派生類中,您可能需要實現這些運算符並簡單地轉發到基類。