1

私の課題は、標準ライブラリのように機能するクラスを作成することListです。最後からデクリメントするときにリンクされたリストの末尾にアクセスする必要があるため、イテレータを正しく機能させることができません。これが私のヘッダーファイルのセクションです:

typedef int T;//for now; eventually will be templated
class list;//**forward declaration, doesn't let other classes know about _tail.**
class Node
{
    //this works fine; class definition removed to make post shorter
};
class list_iterator
{
    private:
        Node* _node;
        list* _list;
    public:
        //constructor
        list_iterator& operator--(){_node=_node?(_node->_prev):(_list->_tail);return *this;}
        //some other declarations
};
class list
{
    friend class list_iterator;
    private:
        Node/*<T>*/ *_head,***_tail**;
        int _size;
    public:
        typedef list_iterator iterator;
        //some constructors and other method declarations
        iterator begin() const {iterator it(_head);return it;}
        iterator end() const {iterator it(0);return it;}
        //more method declarations
};

重要な部分は太字にしてみましたが、アスタリスクで囲っているだけです。注: ほとんどのメンバー関数は cpp ファイルで定義されています。それらはすべて、短い投稿のためにたまたま削除されます。

4

2 に答える 2

4

のメソッド定義をoperator--クラスの外に移動して、リストの後ろ (またはソース ファイル (おそらくより良い考えです。宣言用にヘッダー ファイルを残します)) に配置するだけです。

注: list_iterator 内の宣言はそのままにしておきます

class list_iterator
{
    /* STUFF */
    list_iterator& operator--();
 };
class list
{ 
     /*  STUFF */ 
};

// Now list_iterator::operator-- can see all the members of list.
list_iterator& list_iterator::operator--()
{
    _node=_node?(_node->_prev):(_list->_tail);
    return *this;
}

他のいくつかの回答が示唆するものとは異なります。友情はカプセル化を壊しませ。実際、クラス インターフェイスのフレンド部分を作成することにより、カプセル化が増加します (正しく実行された場合)。ただし、友人をクラスにしっかりとバインドします。

これはまさにイテレータに必要なものです。イテレータが効率的に機能するには、クラスの内部を知る必要があるため、通常はフレンド (または内部クラス) です。クラスの内部動作を公開せずにクラスの使いやすさを向上させますが、イテレータをクラスに緊密に結合するという代償を払います (したがって、クラスを変更する場合は、イテレータの実装を変更する必要があります (ただし、これは予期しないことではありません) )))。

于 2012-07-17T16:29:08.933 に答える
2

はるかに簡単な方法は、リストクラス内にイテレータをネストすることです。

class list { 
    Node *head, *tail;

    class iterator {
        Node *node;
        list *list;
    // ...
    };
};

それを望まない場合は、両方の実装を2つに分割する必要がありますlistlist_iterator最初にメンバー関数のみを宣言するクラス定義、次にメンバー関数の実装です。

class list;

class list_iterator { 
    // ...
    Node *n;
    list *l;
};

class list {
    // ...
    friend class list_iterator;
};

inline list_iterator& list_iterator::operator--(){
    _node=_node?(_node->_prev):(_list->_tail);
    return *this;
}

このように、の定義でlistを定義するまでに宣言されています。次に、で定義されているので、実際に使用する必要のあるコードがあります。list *list_iterator_taillistlist_iterator::operator--list::_tail

于 2012-07-17T16:22:56.523 に答える