用迭代器重写循环的一部分

时间:2013-01-02 17:35:49

标签: c++ iterator

我正试图获取迭代器的挂起,我会发布失败的尝试,但我没有看到一点,所以我只是发布我试图用迭代器重写的代码。

如何让类使用向量的迭代器来跟踪位置而不是制作我自己的临时迭代器?

具体来说,我试图跟踪固定循环内已打印的字母。

实时代码

This is the expected output.

代码预览

#include <vector>
#include <cstdio>

class ABC
{

protected:

   std::vector<char> ABCs;

   int currentLetter;

public:

   ABC():currentLetter( 0 ){}

   void AddLetter( char Letter )
   {
       ABCs.push_back( Letter );
   }

   char getLetter( int position )
   {
       return ABCs.at( position );
   }

   int getLetterPosition()
   {
       return currentLetter;
   }

   void setLetterPosition( int newPosition )
   {
       currentLetter = newPosition;
   }

};

void printSentence( ABC * alphabet, int limit )
{
   for( int i = 0; i < limit; i += 2 )
   {
       printf( "The current letter is %c, the letter after is %c \n", alphabet->getLetter( alphabet->getLetterPosition() ), alphabet->getLetter( alphabet->getLetterPosition() + 1 ) );

       alphabet->setLetterPosition( alphabet->getLetterPosition() + 2 );
   }
}

int main()
{
    ABC alphabet;
    ABC * alphabetPointer = &alphabet;

    for( char letter = 'a'; letter < 'z'; letter++  )
    {
         alphabet.AddLetter( letter );
    }

    printf( "%s\n" , "printSentence() with param of four letters." );
    printSentence( alphabetPointer, 4 );

    //again
    printf( "%s\n" , "printSentence() with param of six letters." );
    printSentence( alphabetPointer, 6 );

    return 0;
}

1 个答案:

答案 0 :(得分:1)

你可以做的是为你自己的向量输入一个常量迭代器,如下所示:

class ABC
{
public:
   typedef std::vector<char> CharCollection;
   typedef typename CharCollection::const_iterator const_iterator;

protected:
   CharCollection ABCs;
   int currentLetter;
   ...

您的课程现在将有一个名为“const_iterator”的类型。

下一步是允许您的类的用户迭代它。 只需实现一个begin()和end()方法,如下所示:

public:
    const_iterator begin()  const {return ABCs.begin();}
    const_iterator end()    const {return ABCs.end();  }
    const_iterator cbegin() const {return ABCs.begin();}
    const_iterator cend()   const {return ABCs.end();  }

请注意,我还实现了新的C ++ cbegin和cend方法。

在这里使用const-iterator非常重要。您不希望呼叫者在您背后更改您的收藏。

现在你可以这样循环:

ABC abc;
...
for (ABC::const_iterator it=abc.begin();it!=abc.end();++it)
   {
   char c = *it;
   ...
   }

您也可以在此使用auto代替ABC::const_iterator

这里有一些陷阱:

  • 如果ABC类中的向量被扩展,指向可能的迭代器将变为无效。因此,您应该清楚地记录您的类的用户在迭代时不得调用任何扩展向量的方法。
  • 您只能有一个开始和一个结束方法。因此,如果向ABC类中添加更多向量,则必须编写beginABC,beginXYZ等方法,以及结束时的方法。

因此,我更倾向于不以这种方式编写它,并将向量作为一个整体暴露给类的用户,如下所示:

class ABC
{
public:
   typedef std::vector<char> CharCollection;
   const CharCollection &getABCs() const {return ABCs;}

这样,调用者可以更清楚地获得集合,但是他无法更改它(它是常量),并且如果ABC类中的某些内容发生更改(因为它返回引用),它将变为无效。 / p>

现在调用者可以选择他想要对集合做什么:

  • 使用CharCollection :: begin()和end()
  • 迭代它
  • 如果他需要在循环时更改ABC类实例
  • ,请复制它
  • 或使用可以处理集合的任何其他STL方法