-1

我试图掌握迭代器的窍门,我会发布失败的尝试,但我没有看到任何意义,所以我只会发布我试图用迭代器重写的代码。

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

具体来说,我试图跟踪固定循环中已经打印了哪些字母。

实时代码

这是预期的输出。

代码预览

#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;
}
4

1 回答 1

1

你可以做的是 typedef 一个常量迭代器到你自己的向量,像这样:

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 方法。

在这里使用常量迭代器很重要。您不希望来电者在您背后更改您的收藏。

现在你可以像这样循环它:

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

您也可以auto在此处使用而不是ABC::const_iterator.

这里有一些陷阱:

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

正因为如此,我一般不喜欢这样写,而是将向量作为一个整体暴露给类的用户,如下所示:

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

这样,调用者就可以更清楚地知道他可以获得集合,但他不能更改它(它是 const),并且如果 ABC 类中的某些内容发生更改,它将变得无效(因为它返回一个引用)。

现在调用者可以选择他想对集合做的任何事情:

  • 使用 CharCollection::begin() 和 end() 对其进行迭代
  • 如果他需要在循环遍历它时更改 ABC 类实例,请复制它
  • 或使用任何其他可以处理集合的 STL 方法
于 2013-01-02T17:52:15.237 回答