2010-12-19 3 views
5

私の現在の割り当ては、イテレータでリストを書いています。イテレータクラスを作成するほどリストに問題はありません。リスト内の - >演算子の意味(と一般的にはC++)

私は、イテレータクラスで定義する2つの演算子、つまりoperator*operator->があります。

これまでのところ素晴らしいです!私のイテレータ構造を想定することは、私はこの二重の間接参照は、&(* pCurr _->データにつながるとして、私は(大規模な何か間違ったことをやって見ることができるので、

// Nested class of List 
class _Iter 
{ 
private: 
    ListElem *pCurr; 
    const List *pList; 

public: 
    _Iter(ListElem *pCurr, const List *list) 
     : pCurr_(pCurr), pList(list) 
    {} 

    T& operator*() { return pCurr_->data; } 
    T* operator->() { return &**this; } 
}; 

ListElemが

// Nested struct of List 
struct ListElem 
{ 
    T data; 

    ListElem *next; 
    ListElem *prev; 
}; 

ことです)、これは逆参照ではありません。

私の主な問題は、この場合実際に何が行われることになっているのか理解できないことです。ユーザーにListElemクラスへのアクセスを許可する必要がありますか?書くだけで

ListElem *operator->() { return pCurr_; } 

ポインタを返すのではなく、

operator*() // Return data pointed to by iterator; pCurr_->data; 
operator->() // Grant access to data-holding structure; pCurr; 

はこの正しいですか、私は何を得ていないのです。私のリスト(そして、できればSTLリスト)で使用されるように、これらの2つの演算子の私の理解では、ということでしょうか? (そして->は、適切な名前を持っていない?)

答えて

5

何をしても、(*something).somethingElsesomething->somethingElseに相当するはずです。後者は、前者の短い構文です。 *thisだけのタイプ_Iter*、ない_Iterを有しているthisを逆参照するので、何operator*()コールが行われないので、したがって、

T& operator*() { return pCurr_->data; } 
T* operator->() { return &**this; } 

は大丈夫です。その後、*thisを逆参照すると、pCurr->dataとなり、そのアドレスを取るので、&pCurr-> dataとなります。しかし、それだけで書くことがより明確になります:operator*()戻りT&operator->()T*を返す必要があれば、それはそれがために設計されたものですので、今

T& operator*() { return pCurr_->data; } 
T* operator->() { return &pCurr->data; } 

、この

ListElem *operator->() { return pCurr_; } 

が間違っています。 ListItemへのアクセス権をデータの代わりに付与したい場合(デザインによっては意味をなさないかもしれませんが、そうでないと思われる場合)、operator*()を再定義して、

ListElem& operator*() { return *pCurr_; } 
ListElem *operator->() { return pCurr_; } 

言語要件ではないことに注意してください。混乱しないようにクラスを設計する方法です。

+0

実際、 'this'は実際にはポインタであることをしばしば忘れています。非常に迷惑な:D – IAE

1

operator->は、この場合(明らかに)pCurr_->dataで、イテレータによって指されるオブジェクトへのポインタを与えます。

T *operator->() { return &(pCurr_->data); } 

これは値または基準としてoperator*()によって返されたオブジェクトのアドレスを返すべきです。

T &operator*() { return pCurr_->data; } 
// or 
T &operator*() { return *operator->(); } 

operator->()(これはポインタに有する挙動を有する)イテレータと->を実装するために存在し、operator*値によって代わりに参照することにより、オブジェクトを返すことができるので、必要です。

必要な機能を得るには、イテレータのListへのポインタを格納する必要はありません。

+1

私は構造体ListElemで質問を更新しました。そして、ああ、Fooへのポインタを提供することで、Foosメソッドのすべてを使用できるようになりました!だから私はListElem自体を返すわけではないが、Fooデータメンバーの機能をユーザーに渡す!それは理にかなっている。 – IAE

+0

@SoulBeaver:私の答えを更新しました。 –

+0

これで、クライアントが使用する基礎データ項目が返されます。イテレータはポインタの一般化であり、同様にデータ項目を指していることを覚えておいてください(時には間接的に、多種類のイテレータを保持するポリモーフィックオブジェクトへのポインタを保持するイテレータを設計したばかりです)。 –

1

あなたの主なガイドラインは

(*iter).hello(); 
iter->hello(); 

の両方が同じことを行う必要があることをする必要があります。それがユーザーの期待です。リターンListElemはユーザに何も与えません。ユーザーはListElemの実装の詳細を知るべきではありません。

関連する問題