How to pass through a container in another class?

I have come across this problem several times and would like to know if there is a simple method or template that I can use to solve it.

Imagine a tree structure in which each node contains an STL container (vector) of pointers to child elements. I want client code to be able to navigate this tree and iterate over child containers to access other parts.

My problem is that I want to support encapsulation for my nodes, while at the same time allowing clients to easily see all the children for this node. I also want to make sure that if the client gets a link to const in the root directory of the node in the tree, then access to subsequent parts of the tree is also constant.

Should I try to create an iterator class for my node type, try using the node tag method, or is there a more elegant template that I am missing?

Edit: I want to emphasize once again that while I see some good ideas, I have containers with pointers for other nodes. The return vector<node *>::const_iteratorwill not impede client calls by non-constant methods on the node. It protects only pointers from pointing to different objects.

+3
source share
3 answers

Something like this is usually enough:

class node 
{
public:
    typedef std::vector<node> node_list;
    typedef node_list::const_iterator const_iterator;

    const_iterator begin() const { return children_.begin(); }
    const_iterator end() const { return children_.end(); }

private:
    node_list children_;
}

, node.

, , , node::const_iterator, , ( std::vector:: const_iterator ), , .

, , , iterator, , .

+4

, . , , , . :

// Derive from this class to create a visitor
class AbstractVisitor
{
public:
    virtual void operator() (const T &) = 0;
};


// Your recursive data-structure class
class MyClass
{
public:
    void walk(AbstractVisitor &v) const
    {
        // Call the client callback
        v(payload);
        for (std::vector<MyClass>::const_iterator it = children.begin();
             it != children.end(); ++it)
        {
            // Recurse
            it->walk(v);
        }
    }

private:
    T payload;   // Some sort of payload associated with the class
    std::vector<MyClass> children;
};


// You could have different visitor classes to do different things
class MyVisitor : public AbstractVisitor
{
public:
    virtual void operator() (const T &t)
    {
        // Do something with t
    }
}


int main()
{
    MyClass m;
    MyVisitor v;
    ...
    m.walk(v);
}

!

+4

To move around the tree, you will need to create your own iterator class, just to navigate through them, you can safely return vector iterators.

0
source

Source: https://habr.com/ru/post/1774336/


All Articles