如何让2个c ++类了解彼此的数据成员?

时间:2012-07-17 16:20:57

标签: c++ class iterator datamember

我的任务是创建一个类似于标准库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文件中定义的;他们都碰巧被删除了一小段文章。

2 个答案:

答案 0 :(得分: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;
}

与其他一些答案不同。 Friendship does NOT break encapsulation。事实上,通过使朋友成为类接口的一部分来增加封装(当正确完成时)。然而,它确实将朋友与班级紧密联系在一起。

这正是迭代器所需要的。为了使迭代器高效工作,它需要知道类的内部,因此它通常是朋友(或内部类)。它增加了类的可用性,而不会暴露类的内部工作,代价是它将迭代器与类紧密耦合(因此,如果你更改类,则需要更改迭代器的实现(但这不是意料之外的) ))。

答案 1 :(得分:2)

到目前为止,最简单的方法是将迭代器嵌套在列表类中:

class list { 
    Node *head, *tail;

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

如果你不想这样做,你需要将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时声明。然后在_tail中定义了list,那么您list_iterator::operator--中的代码实际上需要使用list::_tail ..