私は大学で OOP コース (C++ がベース言語) を勉強しています。私の仕事は、独自のリンク リスト テンプレート コンテナー クラスを実装することです。私はそれをほぼ完全にやりましたが、問題に直面しました。STL は、リストを反復処理するためのiterator
およびクラスを提供することが知られています。const_iterator
それらの実装はほぼ同じです。主な違いは、反復子のメソッドが参照を返すのに対し、const_iterator のメソッドは定数参照を返すことです。https://stackoverflow.com/a/3582733/2108548に従い、別のテンプレート クラスを作成しましたListIterator
。次に、クラスで宣言し、typedef
クラス内で宣言しました。Iterator
ConstIterator
List
私はこのようなものを得ました:
template<typename T>
class ListNode
{
public:
ListNode(T *node_value = nullptr, ListNode *node_prev = nullptr, ListNode *node_next = nullptr):
value(node_value), prev(node_prev), next(node_next) { }
T *value;
ListNode *prev, *next;
};
template<typename T>
class ListIterator
{
typedef ListNode<T> Node;
public:
ListIterator();
ListIterator(Node *node);
ListIterator(ListIterator const &other);
ListIterator &operator++();
// ...
Node *i;
};
template<typename T>
class List: public Container
{
typedef ListIterator<T> Iterator;
typedef ListIterator<T const> ConstIterator;
// ...
Iterator begin() const
{
return Iterator(m_first->next);
}
ConstIterator const_begin() const
{
return ConstIterator(begin());
}
// ...
};
「コピーコンストラクター」を作成することを決定するまで、すべてうまくいきましたIterator
-> ConstIterator
. したがって、 ListIterator<T>
(データ クラス名はどこにT
あるのか) を取得し、新しいオブジェクト タイプを作成するコンストラクタ メソッドが必要ListIterator<T const>
です。しかし、実際にConstIterator
は のコンストラクターはT const
テンプレート パラメーターとして取得されるためconst
、コンストラクターのパラメーターを削除する必要があります。これを行うヘッダーが見つかりましtype_traits
た。だから私は「コピーコンストラクタ」を書きました: typedef typename std::remove_cv::type NoConstT; ListIterator(ListIterator const &other);
しかし、うまくいきません!const_begin() をリクエストした後、次のエラーが発生しました。
List<int> list1;
list1 << 1 << 2 << 3;
int i = *list1.const_begin();
error: 'ListIterator<T>::ListIterator(const ListIterator<typename std::remove_cv<_Tp>::type>&) [with T = int; typename std::remove_cv<_Tp>::type = int]' cannot be overloaded with 'ListIterator<T>::ListIterator(const ListIterator<T>&) [with T = int; ListIterator<T> = ListIterator<int>]'
しかし、それだけではありません。私の目標を達成するには、同様に変換ListNode<T>
する必要があります。ListNode<T const>
しかし、もう 1 つ問題があります。各リスト ノードには、前のノードと次のノードへのポインターが含まれており、ノードのコンストラクターでそれらを初期化しようとすると、再帰が発生します。もちろん、すべてのListNode<T>
ノードをListNode<T const>
反復して変換する関数を作成できます。しかし、私はこの解決策が好きではありません。オーバーヘッドが非常に大きくなります!
私は先生にこの質問をしました。彼は数分間それを理解することができませんでした。— 「でも、私は 3 ~ 4 時間続けました!」— 「もしそうなら、const イテレータを捨てて、それらなしでリスト コンテナをファイナライズしてください。あなたのコードを理解するには時間が必要です」(私の意見では、私のコードは非常に単純です)。私が理解したように、彼はこの質問に対する答えを知りませんでした。でも、作り方が知りたい!どうすればこの問題を解決できますか?
たくさんの間違いをお詫びします — 私は英語のネイティブ スピーカーではありません。