Iterators and C ++ Inheritance

You have a quick question about what would be the best way to implement iterators in the following:

Let's say I have a template “List” of the base class and two subclasses “ListImpl1” and “ListImpl2”. The basic requirement of the base class must be iterable, i.e. I can do:

for(List<T>::iterator it = list->begin(); it != list->end(); it++){
   ...
}

I also want to allow the addition of an iterator, for example:

for(List<T>::iterator it = list->begin()+5; it != list->end(); it++){
   ...
}

Thus, the problem is that the implementation of the iterator for ListImpl1 will be different from the implementation for ListImpl2. I got around this using the ListIterator wrapper containing a pointer to ListIteratorImpl with subclasses of ListIteratorImpl2 and ListIteratorImpl2, but it all gets pretty messy, especially when you need to implement operator + in ListIterator.

Any thoughts on a better design to get around these issues?

+5
5

List<T>::iterator , :

template<typename T>
class List
{
    virtual void add_assign(iterator& left, int right) = 0;

public:
    class iterator
    {
        const List* list;
        const T* item;
    public:
        iterator(const List* list, const T* item) : list(list), item(item) {}

        iterator& operator +=(int right)
        {
            list->add_assign(*this, right);
            return *this;
        }
        static iterator operator +(iterator const& left, int right)
        {
            iterator result = left;
            result += right;
            return result;
        }
    };

    virtual iterator begin() const = 0;
    virtual iterator end() const = 0;
};

(, , ), , :

template<typename T>
class List
{
    class ItImpl
    {
        virtual ItImpl* clone() = 0;
        virtual void increment() = 0;
        virtual void add(int right) = 0;
    };
public:
    class iterator
    {
        ItImpl* impl;
    public:
        // Boring memory management stuff.
        iterator() : impl() {}
        iterator(ItImpl* impl) : impl(impl) {}
        iterator(iterator const& right) : impl(right.impl->clone()) {}
        ~iterator() { delete impl; }
        iterator& operator=(iterator const& right)
        {
            delete impl;
            impl = right.impl->clone();
            return *this;
        }

        // forward operators to virtual calls through impl.
        iterator& operator+=(int right)
        {
            impl->add(right);
            return *this;
        }
        iterator& operator++()
        {
            impl->increment();
            return *this;
        }
    };
};

template<typename T>
static List<T>::iterator operator+(List<T>::iterator const& left, int right)
{
    List<T>::iterator result = left;
    result += right;
    return result;
}

template<typename T>
class MagicList : public List<T>
{
    class MagicItImpl : public ItImpl
    {
        const MagicList* list;
        const magic* the_magic;
        // implement ...
    };
public:
    iterator begin() const { return iterator(new MagicItImpl(this, begin_magic)); }
    iterator end() const { return iterator(new MagicItImpl(this, end_magic)); }
};
+5

- , Iterator Category:

  • InputIterator
  • OutputIterator
  • ForwardIterator
  • BidirectionalIterator
  • RandomAccessIterator

, .

, , - , , .

, .

+1

, , ListImpl1 ListImpl2. ListIterator ListIteratorImpl ListIteratorImpl2 ListIteratorImpl2, , + ListIterator.

, . , , -

class ListIteratorInterface // abstract
{
protected:
  virtual Data& operator*()=0;
  // and other operations
};
class ListIteratorA;
class ListIteratorB; // implementation of the above
class ListIterator
{
  ListIteratorInterface* impl_;
public:
  // when you create this, allocate impl_ on the heap
  // operations, forward anything to impl_
};
0

+ .

Alternatively, you can consider statically polymorphic list classes, rather than run-time polymorphism.

0
source

Say I have a template List with a template and two subclasses ListImpl1 and ListImpl2

What exactly do you get using inheritance here?

0
source

All Articles