0

std::list を使用できません。目標は、任意のデータ型を処理できるユーザー定義の MyList を作成することです。私の問題は、ネストされたイテレータ クラスと、おそらく operator<< をオーバーロードするための関数にあります。私はしばらくこれに取り組んでいましたが、立ち往生しています。締め切りが迫っているので、ここで質問するのは危険を冒すべきだと思います。誰かがこれで私を助けてくれるなら、それは素晴らしいことです。

コードにメモリ リークがあることに気付きましたが、現時点ではそれが主な懸念事項ではありません。また、非常に多くのフレンド関数を持つことは良いプログラミング手法ではないことにも気付きました。後で getData() および setData() 関数を使用してノード内のプライベート変数を取得/設定することを計画しています。

したがって、上記の 2 つの問題は見落としてください...

エラーメッセージ:

"MyList.h", line 67: Error: iterator is not defined.

人々がそれを見る必要がある場合に備えて、ヘッダーファイル全体を含めます。エラーのある 67 行目にコメントを含めます。次に、イテレータを使用してイテレータを設定し、リストを反復処理する方法を示すメイン関数のセクションも含めます。

#include<iostream>
#include<cstddef>

template<class T>
class Node
{
   friend void MyList<T>::push_front(T aData);
   friend void MyList<T>::push_back(T aData);
   friend void MyList<T>::pop_front();
   friend T MyList<T>::front();
   friend void MyList<T>::print();
   friend MyList<T>::~MyList();
   friend std::ostream& operator<<(std::ostream&, Node<T>&);
   private:
      T data;
      Node *next;
      Node *prev;
   public:
      Node(T aData);

};

template<class T>
class MyList
{
   Node<T> *head;
   Node<T> *tail;
   public:
      MyList();
      ~MyList();
      void push_front(T aData);
      void push_back(T aData);
      T front();
      void pop_front();
      void operator=(MyList<T>& another_List);

      void print();  //Test function. Delete later.

      class iterator
      {
         private:
            MyList& object;
            Node<T> *current;
         public:
            iterator(MyList<T>&, Node<T>*);     // iterator a(*this, head);
                                                // MyList<int>::iterator a = list.Begin();
            iterator operator++();          // a++
            iterator operator++(int);           // ++a
            iterator operator--();
            bool operator!=(iterator);
            friend std::ostream& operator<<(std::ostream&, iterator&);
      };

      iterator Begin();
      iterator End();
};

template<class T>
std::ostream& operator<<(std::ostream& out, Node<T>& n)
{
   out << *n.current << ' ';

   return out;
}

template<class T>
std::ostream& operator<<(std::ostream& out, iterator& i)  //ERROR
{
   out << i->current << ' ';

   return out;
}

template<class T>
Node<T>::Node(T aData)
{
   data = aData;
}

template<class T>
MyList<T>::MyList()
{
   head = NULL;
}

template<class T>
MyList<T>::~MyList()
{
   Node<T> *temp;

   while(head != NULL)
   {
      temp = head;
      head = head->next;
      delete temp;
   }
   head = NULL;
}

template<class T>
void MyList<T>::push_front(T aData)
{
   if(head == NULL)
   {
      head = new Node<T>(aData);
      head->next = tail;
      head->prev = NULL;
      tail->prev = head;
   }
   else
   {
      head->prev = new Node<T>(aData);
      head->prev->prev = NULL;
      head->prev->next = head;
      head = head->prev;
   }
}

template<class T>
void MyList<T>::push_back(T aData)
{
   if(head == NULL)
   {
      head = new Node<T>(aData);
      head->prev = NULL;
      head->next = tail;
      tail->prev = head;
   }
   else
   {
      tail->prev->next = new Node<T>(aData);
      tail->prev->next->prev = tail->prev;
      tail->prev->next->next = tail;
      tail->prev = tail->prev->next;
   }
}

template<class T>
T MyList<T>::front()
{
   return head->data;
}

template<class T>
void MyList<T>::pop_front()
{
   if(head == NULL)
      std::cout << "The List is empty!" << endl;
   else
   {
      head = head->next;
      head->prev = NULL;
   }
}

template<class T>
void MyList<T>::print()
{
   while(head != NULL)
   {
      std::cout << "Test print function" << std::endl;
      std::cout << '[' << head->data << ']' << std::endl;
      head = head->next;
   }
   std::cout << "End of test print function" << std::endl;
}

template<class T>
MyList<T>::iterator::iterator(MyList<T>& list, Node<T>* p)
{
   object = list;
   current = p;
}

template<class T>
typename MyList<T>::iterator MyList<T>::iterator::operator++()
{
   if(current == object.tail)
   {
   }
   else
      current = current->next;
   return this;
}

template<class T>
typename MyList<T>::iterator MyList<T>::iterator::operator++(int)
{
   if(current == object.tail)
   {
   }
   else
      current = current->next;
   return this->prev;
}

template<class T>
typename MyList<T>::iterator MyList<T>::iterator::operator--()
{
   if(current == object.head)
   {
   }
   else
      current = current->prev;
   return this;
}

template<class T>
bool MyList<T>::iterator::operator!=(iterator b)
{
   return (this.current == b.current);
}

template<class T>
typename MyList<T>::iterator MyList<T>::Begin()
{
   return iterator(object, head);
}

template<class T>
typename MyList<T>::iterator MyList<T>::End()
{
   return iterator(object, tail);
}

main.cpp

   MyList<int>::iterator i = aList.Begin();
   while(i != aList.End())
   {
      cout << i;
      i++;
   }
4

1 に答える 1

1

クラスの定義iteratorはクラス テンプレートの定義内にネストされているMyListため、 out の外にあるすべてのコードのMyList名前はMyList<whatever>::iterator.

おそらく、エラーを含むコードで少し異なることを意図していたのでしょう。テンプレートとして定義している間:

template<class T>
std::ostream& operator<<(std::ostream& out, iterator& i)  //ERROR
{
   out << i->current << ' ';

   return out;
}

Tテンプレート パラメーター ( ) をまったく使用していないようです。おそらく、あなたは本当に次のようなことを意図していたのでしょう:

template<class iterator>
std::ostream& operator<<(std::ostream& out, iterator& i)  //ERROR
{
   out << i->current << ' ';

   return out;
}

この場合、iteratorhere はテンプレート パラメーターを参照しているだけなので、修飾子を指定する必要はありません。これを使用すると、コンパイラは通常、実際に渡す反復子の型を推測します。

このようにテンプレート パラメーターでイテレーター カテゴリを指定することは不要ですが、多少伝統的であるため、通常はテンプレート パラメーターOutIteratorだけでなく、次のようなものを使用iteratorします。

ただし、これは実際にはあまり一般的ではありません。特に、->current特定のイテレータ型に対してのみ実際に機能することを意味します。より典型的なコードはoperator *反復子の型をオーバーロードするため、クライアント コードは反復子を逆参照するだけです。また、イテレータは通常、参照ではなく値で渡されるほど「軽量」であると想定されていることに注意してください。

class iterator {
    // ...
    T operator*() { return *current; }
};

// ...
template<class OutIt>
std::ostream& operator<<(std::ostream& out, OutIt i)
{
    out << *i << ' ';
    return out;
}
于 2013-06-11T13:56:33.650 に答える