2011-02-24 75 views
0

進出口試圖超載在C++,這樣我可以分配/獲取從像字典我的數據結構的值是在C#中使用的[]操作:重載[]操作在C++

陣列[「的myString」] =等等

這是可能的c + +?

我試圖重載運營商,但它似乎沒有工作,

Record& MyDictionary::operator[] (string& _Key) 
{ 
for (int i = 0; i < used; ++i) 
{ 
    if (Records[i].Key == _Key) 
    { 
     return Records[i]; 
    } 
} 
} 

感謝。

+0

「看起來不起作用」是什麼意思?什麼是「記錄」,「記錄[i]」,「鑰匙」和「使用」?你有沒有考慮過僅僅使用'std :: map',它提供'SortedDictionary'-like功能,或'std :: unordered_map'(如果你的實現提供了它),它提供'Dictionary'-like功能? – 2011-02-24 01:48:32

+1

如果你要寫這樣一個運算符,最好將const加入參數:'Record&MyDictionary :: operator [](const string&_Key)'。 – 2011-02-24 01:57:08

+0

除了Ted的評論,如果沒有const限定符,則執行以下操作將是非法的:'Array [「myString」];'因爲您不能引用臨時對象。不知道我是否正確解釋,我剛剛學到了。 – Marlon 2011-02-24 02:50:33

回答

5

你的代碼是在正確的軌道上 - 你有正確的功能簽名 - 但你的邏輯有點缺陷。特別是,假設你通過這個循環沒有找到你要找的關鍵:

for (int i = 0; i < used; ++i) 
{ 
    if (Records[i].Key == _Key) 
    { 
     return Records[i]; 
    } 
} 

如果發生這種情況,你的函數沒有返回值,這會導致不確定的行爲。由於它正在返回一個引用,所以這可能會導致一次令人討厭的崩潰,第二次嘗試使用該引用。

要解決這個問題,您需要添加一些行爲以確保您不會脫離函數的末尾。一種選擇是將鍵添加到表中,然後返回對新表條目的引用。這是STL std::map類的operator[]函數的行爲。另一種情況是拋出一個例外,說關鍵不在那裏,這有一個有點違反直覺的缺點。

在一個完全無關的筆記中,我應該指出,從技術上講,您不應該將該參數命名爲_Key。 C++標準規定,任何以兩個下劃線(即__myFunction)開頭的標識符名稱,或者一個下劃線後跟一個大寫字母(如您的_Key示例中)都會被實現保留以用於他們認爲有必要的任何目的。他們可以將#define的標識符變爲無意義的東西,或者將其映射到某些編譯器本身。如果您從一個平臺移動到另一個平臺,這可能會導致您的程序停止編譯。要解決此問題,請使K小寫(_key),或完全刪除下劃線(Key)。

希望這會有所幫助!

+0

謝謝。它似乎並沒有工作,但至少intellisense沒有接受它。如果我鍵入do MyDictionary [「myString」]它說它必須是一個int或枚舉類型。我需要以某種方式使用const嗎? – Sean 2011-02-24 02:18:24

+1

請提供有問題的代碼。 'MyDictionary [「myString」]似乎混淆了類型和實例。 – Keith 2011-02-24 02:32:17

+0

myDictionary = MyDictionary :: Instance(); (單例模式)記錄測試= myDictionary [「測試」] - >(沒有出現)錯誤說「測試」必須是整數或枚舉類型。然而,這工作,記錄測試= myDictionary->運營商[](「測試」); – Sean 2011-02-24 02:38:25

0

在相關說明中,operator[](const Key& key)的一個問題是,如templatetypedef所述,爲了返回引用,它需要爲非const。

要擁有一個const訪問器,您需要一個可以返回失敗案例值的方法。在STL中,這是通過使用find()來完成的,迭代器的使用和end()表示失敗。

另一種方法是返回一個指針,其中null指示失敗。這在默認構建的記錄毫無意義的情況下可能是合理的。這也可以用數組運算符來完成:

Record* MyDictionary::operator[] (const string& keyToFind) const 
{ 

    for (int i = 0; i < used; ++i) 
    { 
     if (Records[i].Key == keyToFind) 
     { 
      return &Records[i]; 
     } 
    } 
    return 0; 
} 

當然是有一種觀點認爲,應該operator[]返回一個參考。在這種情況下,您最有可能實施find(),並在其中實施operator[]

要實現find(),你需要定義一個迭代器類型。方便的類型將取決於實施。例如,如果Records []是普通的舊數組:

typedef Record* iterator; 
typedef const Record* const_iterator; 
const_iterator MyDictionary::end()const 
{ 
    return Records + used; 
} 
const_iterator MyDictionary::begin() const 
{ 
    return Records; 
} 
const_iterator MyDictionary::find(const string& keyToFind) const 
{ 
    for (iterator it = begin(); it != end(); ++it) 
    { 
     if (it->Key == keyToFind) 
     { 
      return it; 
     } 
    } 
    return end(); 
} 
+0

任何地方我可以找到關於如何自己實現find()和end()的文檔? – Sean 2011-02-24 03:12:33

+0

@Sean,見編輯。 – Keith 2011-02-24 04:04:23