2014-01-09 2 views
4

이 문제와 관련된 다른 스레드를 읽었지만 내 문제의 해결책은 제공되지 않았습니다. 나는 너희들이 나에게 아이디어 나 충고를 줄 수 있기를 바란다.const가 아닌 클래스에 대해 const_iterator를 호출하는 방법은 무엇입니까?

Map이라는 클래스를 구현하려고합니다. 2 개의 반복자 - iteratorconst_iterator을 포함해야합니다.

나는 그들을 구현 - iterator 상속을 const_iterator에서, 그리고 Map 클래스 I는 다음과 같은 기능이 : 우리가 구현하는 데 필요한 상황을 확인하기 위해 예를 들어 파일을 주어진

iterator begin(); 
iterator end(); 
const_iterator begin() const; 
const_iterator end() const; 

합니다. msi 이후

Map<std::string,int> msi; 

...

// print map 
for(Map<std::string,int>::const_iterator it = msi.begin(); it != msi.end(); ++it) { 
// more stuff here 
} 

는 const가 아닌지도 인스턴스, 의도하지 않은 행동의 결과로 msi.begin()iterator begin() 호출하지 const_iterator begin() const입니다 : 거기에, 다음과 같은 코드가있다.

예제 파일이 괜찮다고 가정하면 어떻게해야합니까? msi.begin()은 올바른 const_iterator 함수를 호출합니까? (iterator를 고려하면 const_iterator입니다).

편집 : 자동 변환에 대한 이야기에 관해서는 필자의 반복기 클래스를 추가하기로 결정 했으므로 실수를 지적하시기 바랍니다.

class Map { 

    //... 

    public: 

     class const_iterator { 

     private: 

      Node* currNode; 

     public: 


      const_iterator(Node* cur_node = NULL) : currNode(cur_node) {} 

      const_iterator& operator++() { 
       currNode = currNode->next; 
       return *this; 
      } 

      const_iterator operator++(int) { 
       const_iterator old = *this; 
       ++(*this); 
       return old; 
      } 

      bool operator!=(const_iterator const& curr) { 

       return !(*this == curr); 
      } 

      string operator*() { 
       // this might cause memory leak 
       string toString(this->currNode->key); 
       std::stringstream s; 
       int tmp = this->currNode->value; 
       s << tmp; 
       string secondString(s.str()); 
       toString = toString + ":" + secondString; 
       return toString; 
      } 

      bool operator==(const_iterator const& curr) { 
       return this->currNode == curr.currNode; 
      } 


      void operator=(const_iterator target) { 
       this = target; 
      } 

      //void operator=(Node* target) { 
      // this->currNode = target; 
      //} 
     }; 

     class iterator : public const_iterator { 

     private: 

      Node* currNode; 

     public: 

      iterator(Node* cur_node = NULL) : currNode(cur_node) {} 

      iterator& operator++() { 
       currNode = currNode->next; 
       return *this; 
      } 

      iterator operator++(int) { 
       iterator old = *this; 
       ++(*this); 
       return old; 
      } 

      bool operator==(iterator const& curr) { 
       return *this == curr; 
      } 

      bool operator!=(iterator const& curr) { 

       return !(*this == curr); 
      } 

      string operator*() { 
       // this might cause memory leak 
       string toString(this->currNode->key); 
       std::stringstream s; 
       int tmp = this->currNode->value; 
       s << tmp; 
       string secondString(s.str()); 
       toString = toString + ":" + secondString; 
       return toString; 
      } 

      void operator=(iterator target) { 
       this = target; 
      } 

     }; 

     //.. 
} 
+0

정확하게? – Yakk

답변

7

C++ 11 개 표준 컨테이너는 그 목적을 위해 cbegincend를 추가합니다. 그것이 없다면 분명히 객체를 const&으로 명시 적으로 캐스팅하여 객체에 const 뷰를 가져올 수 있습니다.

그러나 더 근본적으로 iteratorconst_iterator으로 자동 변환을 지원해서는 안됩니다. 이와 같이 클라이언트 코드를 전혀 변경할 필요가 없습니다. 사실, 당신의 코드는 이미 말했듯이 iteratorconst_iterator에서 상속 받으면 이것을 지원해야합니다.

그러나 게시 한 코드에는 몇 가지 오류가 있습니다. 첫째, operator=이 잘못되었으므로 오류가 발생했습니다. 수정 된 버전은 다음과 같습니다.

void operator=(const_iterator target) { 
    currNode = target.currNode; 
} 

더 중요한 점은 상속이 이해가되지 않는다는 것입니다. 사실, 을 수행하면이 에서 const_iterator으로 상속되지만이 코드는 전혀 발생하지 않은 것으로 가장합니다. iterator은 상위 클래스를 완전히 다시 구현하고 어떤 식 으로든 관련되지 않습니다.

iterator 오히려 다음과 비슷한 모습이 될 것입니다

class iterator : public const_iterator { 
public: 
    iterator(Node* cur_node = NULL) : const_iterator(cur_node) {} 
}; 

currNodeconst_iteratorprotected을 선언 물론 필요합니다. 그 클래스는 const_iterator 클래스에 어떤 기능도 추가하지 않기 때문에 완전히 쓸모가 없습니다.값을 수정할 수있는 operator*을 구현해야합니다. 현재 코드는 맵 값에 대한 참조가 아닌 새로 생성 된 문자열을 반환하기 때문에 근본적으로 허용하지 않습니다.

또한 const_iterator 클래스가 처음에 비 constNode 포인터를 가져 오는 방법이 명확하지 않습니다. 그것은 가능하지 않아야합니다 : 결국 포인터는 const Map에서 가져옵니다.

+1

'템플릿 T const & as_const (T & v) {return v; } // wheee' – Xeo

+0

자동 변환을 구현하는 방법을 확장 할 수 있습니까? 나는 OP가 그것을하는 방법을 알고 있다면 그들이 가질 것이라고 생각합니다. – deworde

+0

@deworde OP에 따르면 변환 *은 이미 구현되어 있습니다 ("iterator'는'const_iterator'에서 상속됩니다). –

0

당신은) MSI

const Map<std::string,int> msi; 

대신 ((시작)과 끝의

Map<std::string,int> msi; 

CONST 버전을 정의합니다 호출 할 경우 왜 나쁜`iterator` 버전을 호출

관련 문제