2014-01-09 37 views
4

我讀了一些與此問題有關的其他線程,但沒有提供解決我的問題。我希望你們能給我一些想法或建議。如何爲非const類調用const_iterator?

我試圖實現這個類Map。它應該包含2個迭代器 - iteratorconst_iterator

我讓他們實現 - 從const_iteratoriterator繼承,並在Map I類具有以下功能:

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

我們得到了一個示例文件,看看有什麼是落實需要。 在那裏,有下面的代碼:

Map<std::string,int> msi; 

...

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

因爲msi是一個非const地圖實例,msi.begin()調用iterator begin()而不是const_iterator begin() const,導致意外情況。

假設示例文件沒問題,我該如何讓msi.begin()調用正確的const_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

爲什麼調用'iterator'版本壞究竟? – Yakk

回答

7

C++ 11個標準集裝箱添加cbegincend用於這一目的。缺乏這一點,你顯然總是可以明確地將你的對象投射到const&以獲得對象的const視圖。

然而更基本的是,您的iterator不應該支持自動轉換爲const_iterator。像那樣,你根本不需要改變客戶端代碼。實際上,如果您已經說過iterator繼承自const_iterator,那麼您的代碼應該已經支持此功能。

但是,您發佈的代碼包含多個錯誤。首先,operator=是錯誤的,您應該收到它的錯誤。更正後的版本是:

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

更重要的是,你的繼承沒有任何意義。確實,你const_iterator繼承iterator,但你的代碼假裝這從未發生 - iterator完全重新實現它的父類,並不以任何方式與它有關。

iterator倒是應該是這個樣子:

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

這就要求currNodeconst_iterator宣佈protected當然。這個類也是完全沒用的(但目前你的類也是如此),因爲它不會爲const_iterator類增加任何功能。您需要實施允許修改其值的operator*。你當前的代碼基本上不允許這樣做,因爲它返回一個新創建的字符串,而不是(類似於)對地圖值的引用。

此外,目前還不清楚const_iterator類首先得到非指針指針的位置。這應該是不可能的:畢竟它從const Map得到指針。

+1

' template 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; 

,而不是開始()和end(的

Map<std::string,int> msi; 

const版本)將被調用

相關問題