2016-04-03 29 views
0

"Harita" olarak adlandırılan C# sözlük sınıfının basitleştirilmiş bir versiyonu olan bir şablon sınıfı oluşturmaya çalışıyorum. Sahip olduğum problem [] operatör aşırı yükü ve = operatör aşırı yükü.Operatör aşırı yüklenmesi [] ve =

[] operatör aşırı yüklenmesi, mapObject [“keyString”] = value gibi bir ifadeye izin verecek şekilde aşırı yüklenmelidir; Böyle durumlarda anahtarın mevcut olmaması durumunda bir istisna atılmalıdır. Aşırı yüklenen bir operatör, bir derin kopya yapmalıdır.

Neyi yanlış yapıyorum?

#pragma once 
#include <iostream> 
#include <ostream> 

using namespace std; 

template<class K, class V> 
class Map; 

template <class K, class V> 
class Entry; 

//template<class K, class V> 
//Map<K, V>& operator[](K* sKey); 

template<class K, class V> 
ostream& operator<< <>(ostream& os, const Map<K, V>& L); 

template <class K, class V> 
class Map 
{ 
protected: 
    Entry<K, V>  **ledger; 
    Entry<K, V>  **temp; 
    int    numOfEntries; 

public: 
    V    *valArray; 

    Map(); 
    Map(const Map<K, V>& mapObject); 
    ~Map(); 

    void ledgerAllocation(); 
    void tempAllocation(); 
    void entrySizePlus(); 
    void ledgerCopy(); 
    void tempCopy(); 
    void AddEntry(K key, V value); 

    Map<K, V>& operator[](K* sKey); 
    friend ostream& operator<< <>(ostream& os, const Map& L); 
    Map<K, V>& operator=(const Map<K, V>& toBeCopied); 
}; 


//Default constructor, might change at a later stage... 
template<class K, class V> 
Map<K, V>::Map() 
{ 
    numOfEntries = 1; 
} 

template<class K, class V> 
inline Map<K, V>::Map(const Map<K, V>& mapObject) 
{ 
    ledger = new Entry<K, V>*; 
    numOfEntries = 1; 
    ledger = mapObject.ledger 
} 

//Default destructor, will need to change it later to properly delete an allocated array. 
template<class K, class V> 
Map<K, V>::~Map() 
{ 
} 

template<class K, class V> 
inline void Map<K, V>::ledgerAllocation() 
{ 
    ledger = new Entry<K, V>*[numOfEntries]; 

    for (int i = 0; i < numOfEntries; i++) 
    { 
     ledger[i] = new Entry<K, V>; 
    } 
} 

template<class K, class V> 
inline void Map<K, V>::tempAllocation() 
{ 
    temp = new Entry<K, V>*[numOfEntries]; 

    for (int i = 0; i < numOfEntries; i++) 
    { 
     temp[i] = new Entry<K, V>; 
    } 
} 

template<class K, class V> 
inline void Map<K, V>::entrySizePlus() 
{ 
    tempAllocation(); 
    ledgerCopy(); 

    ledgerAllocation(); 
    tempCopy(); 
} 

template<class K, class V> 
inline void Map<K, V>::ledgerCopy() 
{ 
    tempAllocation(); 
    K cKey; 
    V cValue; 

    for (int i = 0; i < numOfEntries - 1; i++) 
    { 
     cKey = ledger[i]->getKey(); 
     cValue = ledger[i]->getValue(); 
     temp[i]->setKeyandValue(cKey, cValue); 
    } 
} 

template<class K, class V> 
inline void Map<K, V>::tempCopy() 
{ 
    ledgerAllocation(); 
    K cKey; 
    V cValue; 

    for (int i = 0; i < numOfEntries - 1; i++) 
    { 
     cKey = temp[i]->getKey(); 
     cValue = temp[i]->getValue(); 
     ledger[i]->setKeyandValue(cKey, cValue); 
    } 
} 

//Function that will add a new Key and Value to a new map-object within the array. 
template<class K, class V> 
void Map<K, V>::AddEntry(K newKey, V newValue) 
{ 

    if (numOfEntries <= 1) 
    { 
     ledgerAllocation(); 
    } 
    else 
    { 
     entrySizePlus(); 
    } 

    this->ledger[numOfEntries - 1]->setKeyandValue(newKey, newValue); 
    numOfEntries++; 
} 


template<class K, class V> 
Map<K, V>& Map<K, V>::operator[](K * sKey) 
{ 
    K Akey; 
    V Avalue; 

    for (int i = 0; i < numOfEntries; i++) 
    { 
     Akey = ledger[i]->getKey(); 
     Avalue = ledger[i]->getValue(); 

     if (Akey == *sKey) 
     { 
      return Avalue; 
     } 
     else 
     { 
      throw string("Key does not exist"); 
     } 
    } 
} 

template<class K, class V> 
Map<K, V>& Map<K, V>::operator=(const Map<K, V>& toBeCopied) 
{ 
    if (ledger == toBeCopied) 
    { 
     return *this; 
    } 
    ledger = toBeCopied.ledger; 

    return *this; 
} 

//Overloads the "<<" so that the command: cout << mapObject << endl; can be used to print the entire map. 
template<class K, class V> 
ostream & operator<< <>(ostream& os, const Map<K, V>& L) 
{ 
    K pKey; 
    V pValue; 

    for (int i = 0; i < L.numOfEntries - 1; i++) 
    { 
     pKey = L.ledger[i]->getKey(); 
     pValue = L.ledger[i]->getValue(); 
     os << "[" << pKey << " , " << pValue << "]"; 
     if (i < L.numOfEntries - 2) 
     { 
      cout << " , "; 
     } 
    } 
    return os; 
} 


template <class K, class V> 
class Entry 
{ 
protected: 
    K key; 
    V value; 

public: 
    Entry(); 
    ~Entry(); 

    void setKeyandValue(K skey, V sValue); 
    K getKey(); 
    V getValue(); 
    void printKeyandValue(); 

}; 


template<class K, class V> 
Entry<K, V>::Entry() 
{ 
    this->key = NULL; 
    this->value = NULL; 
} 

template<class K, class V> 
Entry<K, V>::~Entry() 
{ 
} 

template<class K, class V> 
inline void Entry<K, V>::setKeyandValue(K skey, V sValue) 
{ 
    key = skey; 
    value = sValue; 
} 

template<class K, class V> 
inline K Entry<K, V>::getKey() 
{ 
    return this->key; 
} 

template<class K, class V> 
inline V Entry<K, V>::getValue() 
{ 
    return this->value; 
} 

template<class K, class V> 
void Entry<K, V>::printKeyandValue() 
{ 
    cout << this->key << ": " << this->value << endl; 
} 
+1

std :: map' türünün farkındasınız, ya sen? – davidhigh

+0

Evet, ama kendi versiyonumu yapmaya çalışıyorum. – alifarlig

+4

tamam, tabi. O zaman kodu asıl soruna doğru indirmeyi öneririm. – davidhigh

cevap

0
Akey = ledger[i]->getKey(); 
    Avalue = ledger[i]->getValue(); 

    if (Akey == *sKey) 
    { 
     return Avalue; 

    // ... 

Ne burada yanlış yapıyoruz, kapsam zaman bu işlev döndürür dışına gider bir nesneye bir başvuru dönüyoruz olmasıdır. Bu işlev döndüğünde, bu başvuru artık geçerli değil. İşte

Avalue = ledger[i]->getValue(); 

, sen getValue() çağırarak ve bu işlevde duyurulan "yerel" bir nesne bir nesne içine bu yöntem çağrısının sonucunu yerleştiriyoruz.

Ve bu, bu nesneye bir başvuru döndürür. Fakat bu, bu işlevin yerel bir nesnesi olduğu için, bu nesne döndükçe, nesne artık mevcut değildir.

Genel yaklaşımınız doğru, sizin referansınız operator[]. Ancak, bir "yerel" nesnesi yerine, operator[] yönteminde oluşturulan geçici bir nesne yerine kapsayıcınızdaki orijinal değere bir başvuru göndermeniz ve bu yöntem döndüğünde imha etmeniz gerekir.

+0

Bu yüzden hala Akey kullanabiliyorum = muhasebeci [i] -> getKey(); Anahtarları karşılaştırmak için? – alifarlig

+0

Anahtarların karşılaştırılması, doğru bir şekilde değerin döndürülmesiyle ilgili bir şey yapmaz. –

+0

Böylece V Avalue'yi kaldırabilirim; Avalue = muhasebeci [i] -> getValue(); Avalue; Ve iade defteri [i] .value gibi bir şeyle değiştirin; ? – alifarlig

0

Aşırı yüklenen bir kullanıcı, bir derin kopya yapmalıdır.

Map<K, V>& Map<K, V>::operator=(const Map<K, V>& toBeCopied) Satır: ledger = toBeCopied.ledger;, derin bir kopya gerçekleştirmez. Her iki nesne de aynı deftere işaret eder.

İlgili konular