2013-02-04 72 views
1

我有一個問題,我們有一些重載函數,但是當它們被第二個參數調用不同類型時,它們總是調用CString版本,而不是適當的過載。C++參數類型轉換

帶有函數的想法是作爲一種基於密鑰從緩存中獲取和存儲值的方法,但問題是編譯器選擇調用錯誤的函數。

的函數的定義是:

bool GetProcessDataItem(LPCTSTR lpszName, CString& strValue, int iIndex = 0, bool bLeveled = false); 
bool GetProcessDataItem(LPCTSTR lpszName, int& iValue, int iIndex = 0, bool bLeveled = false); 
bool GetProcessDataItem(LPCTSTR lpszName, long& lValue, int iIndex = 0, bool bLeveled = false); 
bool GetProcessDataItem(LPCTSTR lpszName, double& dValue,int iIndex = 0, bool bLeveled = false); 
bool GetProcessDataItem(LPCTSTR lpszName, ATime& tmValue,int iIndex = 0, bool bLeveled = false); 

void SetProcessDataItem(LPCTSTR lpszName, const CString& strValue, int iIndex = 0, bool bLeveled = false); 
void SetProcessDataItem(LPCTSTR lpszName, int& iValue, int iIndex = 0, bool bLeveled = false); 
void SetProcessDataItem(LPCTSTR lpszName, long& lValue, int iIndex = 0, bool bLeveled = false); 
void SetProcessDataItem(LPCTSTR lpszName, double& dValue, int iIndex = 0, bool bLeveled = false); 
void SetProcessDataItem(LPCTSTR lpszName, ATime& tmValue, int iIndex = 0, bool bLeveled = false); 

所以下面的工作確定:

const CString aString = "blah" 
SetProcessDataItem("FOO", aString)); 

CString tmpString; //to be populated by the Get() call below 
GetProcessDataItem("FOO", tmpString); //tmpString == "blah" 

但這並不:

const double aDouble = 123; 
SetProcessDataItem("FOO", aDouble)); //Calls the CString overloaded function (which doesn't convert double -> CString properly, so we get jibberish!) 

double tmpDouble = 0; 
GetProcessDataItem("FOO", tmpDouble); //Calls the CString overloaded function and gets the gibberish that was originally passed in above 

我們使用Visual Studio 6作爲我們的編譯器(不,升級不是我希望的那樣多),在Windows XP和7上。

+1

這似乎是編譯器中的一個嚴重錯誤。你有沒有嘗試過做一個明確的類型轉換(如果不需要的話)?此外,哪些重載被調用,有或沒有'const CString&'? –

+1

大多數所謂的C++編譯器都不完全符合標準,但MSVC 6如此陳舊而且破損,實在不配稱爲C++編譯器。此外,請認識到我們對您的問題的回答可能不適用於VC6,因爲它們通常基於標準C++。 – PlasmaHH

回答

0

嗯,我覺得這是一個問題,VS6畢竟作爲解決辦法是改變聲明這樣:

bool GetProcessDataItem(LPCTSTR lpszName, int& iValue, int iIndex = 0, bool bLeveled = false); 
bool GetProcessDataItem(LPCTSTR lpszName, long& lValue, int iIndex = 0, bool bLeveled = false); 
bool GetProcessDataItem(LPCTSTR lpszName, double& dValue,int iIndex = 0, bool bLeveled = false); 
bool GetProcessDataItem(LPCTSTR lpszName, ATime& tmValue,int iIndex = 0, bool bLeveled = false); 
bool GetProcessDataItem(LPCTSTR lpszName, CString& strValue, int iIndex = 0, bool bLeveled = false); 

void SetProcessDataItem(LPCTSTR lpszName, const int iValue, int iIndex = 0, bool bLeveled = false); 
void SetProcessDataItem(LPCTSTR lpszName, const long lValue, int iIndex = 0, bool bLeveled = false); 
void SetProcessDataItem(LPCTSTR lpszName, const double dValue, int iIndex = 0, bool bLeveled = false); 
void SetProcessDataItem(LPCTSTR lpszName, const ATime& tmValue, int iIndex = 0, bool bLeveled = false); 
void SetProcessDataItem(LPCTSTR lpszName, const CString& strValue, int iIndex = 0, bool bLeveled = false); 

看到區別?

是的,那裏幾乎沒有一個。我在頭文件中聲明瞭CString版本的函數,刪除了取值爲int,longdouble的設置函數的引用,並且還在set函數const中創建了參數。

我認爲,VS6編譯器只是發現第一個功能過載,即使它不是最合適的,它會執行並使用它。

+0

這在我看來似乎是一個編譯器錯誤。 –

2

我認爲這是由CString可以從任何其他類型生成的事實引起的。你可能會發現你需要使CString版本成爲一個不同的簽名 - 可能會添加另一個整數或其他的數字。

但也許更好的解決方案是有一個CString的包裝,使編譯器不會自動選擇CString版本,即使其他人都適合。

例如,

class CStringWrapper 
{ 
    CStringWrapper(CString &x) : wrapped(x) {} explicit; 
    private: 
    CString& wrapped; 
}; 

現在,編譯器不會轉換,自動將CStringWrapper。當然,這意味着你必須使用CStringWrapper(mystring)來調用需要使用CString的函數,但是我認爲這比不作爲CString的evyerthing差。

+0

我認爲你對任何可轉換爲CString的東西都是正確的。我發現移動函數聲明的順序使它首先找到了首選方法,然後在最後使用CString – fwgx