2012-09-28 4 views
2

C++의 간단한 해시 테이블에서 작업하고 있습니다. 지정된 키에 대한 해시 테이블을 삽입, 삭제 및 검색하는 메소드가 있습니다. C++ Map STL 컨테이너가 내 상황을 처리 할 수 ​​있다는 것을 알고 있지만 교육용으로 코드를 작성하고 싶습니다.해시 테이블에 대한 벡터에 대한 오버로드 된 [] 연산자

기본적으로 나는 단일 문자열을 가져 와서 다른 문자열의 벡터에 매핑하는 해시 테이블을 가지고 있습니다. .Add() 또는 .Delete()를 호출하면 예상대로 작동하기 때문에 메서드에서 쉽게 수행 할 수 있습니다. 그러나 벡터에서 이러한 작업을 수행 할 수있는 클래스에 오버로드 된 [] 연산자를 생성하려고합니다. 내가 벡터에 항목을 추가하려면

예를 들어,이 같은 것을 쓸 수 있습니다 :

 
    hashTable[string1] = newString; 

이 내 벡터의 구성원으로 새 문자열을 설정합니다. 삭제와 검색에서도 마찬가지입니다.

 
    hashTable[string1] = ""; 
    cout << hashTable[string1] << endl; 

내 주요 문제는이 기능을 얻을 수있는 [] 연산자를 오버로드하는 방법을 모른다는 것이다. 지금이 기능이 코딩되어 있습니다. 기본 1 대 1 문자열 일치는 작동하지만 문자열 대 벡터 일치는 작동하지 않습니다.

 
    //Return a reference to a vector to update then reassign? 

     vector& HashClass::operator[](const string index) 
     { 
      assert(size >= 0 && size < maxSize); 
      Hash(key); 
      return hashTable[index];  
     } 

내가 생각하기에 나는 나중에 벡터 할당을해야한다고 생각하고있다. 사용자로서, 나는이 kludgy를 발견 할 것이다.

+0

저는 개인적으로 문제가 어디 있는지 이해하지 못했습니다 ... (단지 나 일 수 있음) –

+0

2 가지 다른 반환 유형을 원하십니까? 하나의 오버로드 된 연산자 []는 문자열을 반환하고 다른 오버로드는 벡터를 반환합니다. – sashang

+0

작성한 글에서 각 키에 대해 하나 이상의 문자열이 있는지 여부는 분명하지 않습니다. –

답변

0

C++에서 연관 컨테이너에 대한 액세스는 일반적으로 매핑 된 유형의 객체를 생성하고 키로 삽입 한 다음 삽입 된 매핑 된 객체에 대한 참조를 반환하는 기본 의미를 부여받습니다.

string& HashClass::operator[](const string index) 
    { 
     assert(size >= 0 && size < maxSize); 
     Hash(key); 
     vector &v = hashTable[index];  
     if (index in v) { 
      ... 
     } else { 
      v.push_back(string()); 
      return v.back(); 
     } 
    } 
0

밀접하게 다른 질문에 관련이 질문 : 당신이 할당보다 다른 존재하지 않는 값을 액세스 할 때 당신이 원하는 않는 어떤 행동

그래서 operator[]는 다음과 같이 구현 될 것이다 당신?

std::cout << hashTable[string] << std::endl; 

string 테이블에 존재하지 : 다른 말로하면, 당신은 무엇을 당신이 쓸 때 발생할까요?

두 가지 접근 방법이 있습니다. 오류로 간주하여 예외를 발생 시키거나 중단하거나 이와 유사한 것으로 간주 할 수 있습니다. 을 기본 생성자를 사용하여 작성하거나 클라이언트를 으로 이전에 반환 할 수 있습니다.

표준 맵과 unordered_map은 두 번째 방법 인 기본 생성자를 사용하여 새 값을 생성합니다. 이렇게하면 매우 간단한 솔루션을 사용할 수 있습니다. operator[]이 없으면이 값을 삽입하여 을 기본값으로 초기화합니다. 그런 다음 그것에 대한 참조를 반환합니다. hashTable[string] = newString;은 참조를 통해 이미 존재하는 값을 지정합니다. (당신이 operator[] 뭔가를 찾거나하지 않습니다 여부 앞을 테스트 할 수 있도록, 아마도 contains 기능)

많은 사용의 경우, 첫 번째 방법이 바람직 할 것이다.첫 번째 방법을 구현하려면, 당신은 처음 액세스의 각 유형에 대한 특정 기능을 구현해야합니다

template <typename Key, typename Value> 
class HashTable 
{ 
public: 
    Value* get(Key const& key) const; 
    void set(Key const& key, Value const& value); 
}; 

(나는 일반적으로 이러한 공개, 하여 클라이언트를 자신의 사용을 금지 할 이유가 없습니다.)

template <typename Key, typename Value> 
class HashTable 
{ 
public: 
    class Proxy 
    { 
     HashTable* myOwner; 
     Key myKey; 
    public: 
     Proxy(HashTable* owner, Key const& key) 
      : myOwner(owner) 
      , myKey(key) 
     { 
     } 

     operator Value const&() const 
     { 
      Value const* result = myOwner->get(myKey); 
      if (result == NULL) { 
       // Desired error behavior here... 
      } 
      return *result; 
     } 

     Proxy const& operator==(Value const& value) const 
     { 
      myOwner->set(myKey, value); 
      return *this; 
     } 
    }; 

    Value* get(Key const& key) const; 
    void set(Key const& key, Value const& value); 

    Proxy operator[](Key const& key) 
    { 
     return Proxy(this, key); 
    } 
}; 

을 따라서 당신이 쓸 때, : 다음과 같이 그런 다음, 프록시를 반환 operator[]을 정의

hashTable[key] = newString; 

프록시의 operator=hashTable.put(key, newString)을 호출합니다. 그러나 다른 컨텍스트에서는 을 의 암시 적 유형 변환이라고 부르며이 프록시는 hashTable.get(key)을 호출합니다. 어떤 경우에는

, 당신은 기본 값을 반환하고자 할 경우에도,이 솔루션을 사용하는 것이 바람직 수 있습니다 다음 get 기능이 해시 테이블에 아무것도 삽입 에 필요하지 않습니다, 그래서 표는 기입하지 않습니다 최대 의 실수로 operator[]const에 오버로드 할 수 있으므로 const 해시 테이블에서도 사용할 수 있습니다. 또한 값 형식에 기본 생성자가 필요하지 않습니다.

표준에서 사용되는 용액과 관련하여 하나의 단점이있다. 당신이 operator.를 오버로드 할 수 없기 때문에, 당신은 프록시의 참조처럼 행동 할 수 없습니다, 사물과 같은 :

hashTable[string].someFunction(); 

가 작동하지 않습니다. A-주위 작품은 프록시에 operator-> 과부하이지만, 이 다소 부 자연스러운 구문 이어진다.

hashTable[string]->someFunction(); // But the hash table contains 
            // values, not pointers!!! 

(참고로 암시 적 변환에 의해 오도 될 암시 적 변환이되지 않습니다하지 마십시오 의 표현식에 대해 생각합니다. a.b.

관련 문제