С++ абстрактный класс с вложенным классом. производный класс и вложенный класс

У меня есть задача написать собственные контейнеры Linked_list и Array_list. У меня есть один интерфейс для них:

typedef int value_type;
class Container 
{
public:
        class Iterator 
        {   
        public:
            Iterator();
            Iterator(value_type* other);
            Iterator(const Iterator& other);
            Iterator& operator=(const Iterator& other);
                    ...
        };

    Container();
    Container(const Container& other);
    ~Container();   

    virtual value_type& front() const=0;
    virtual value_type& back() const=0;
    virtual Iterator begin() const=0; // 
    ...
};

Я сделал производные классы Linked_list и Array_list:

class Linked_list:public Container 
{
public:
    long int cur_size;
    List elem;
    static Link end_;
    class Iterator: public Container::Iterator
    {
        friend Linked_list;
        Link *p;    
    };

    Iterator begin() const; //overriding virtual function return type differs ...

...
}

Я думаю, все неправильно. должен ли вложенный класс Linked_list::Iterator быть производным классом? Можно ли это сделать, если я не могу изменить интерфейс?

Ответ 1

Принимая во внимание ваши ограничения по дизайну, которые вы не можете использовать шаблоны, необходимо изменить одно: добавить интерфейс IteratorImpl. Таким образом, вы можете сделать class Iterator из базы class Container не виртуальной. Он должен быть не виртуальным, поскольку STL-итераторы должны иметь семантику значений. См. pimpl idiom для более подробной информации о том, как это работает!

Вот так:

typedef int value_type;
class Container 
{
    protected:
        class IteratorImpl
        {   
        public:
            virtual void next() = 0;
            virtual IteratorImpl* clone() const = 0;
            virtual value_type get() const = 0;
            virtual bool isEqual(const IteratorImpl& other) const = 0;
        };

    public:
        class Iterator 
        {   
        public:
            Iterator(IteratorImpl* impl) : impl(impl) {}
            ~Iterator() { delete impl; }
            Iterator(const Iterator& other) : impl(other.impl->clone()) {}
            Iterator& operator=(const Iterator& other) {
              IteratorImpl* oldImpl = impl;
              impl = other.impl->clone();
              delete oldImpl;
            }
            bool operator == (const Iterator& other) const 
            {
               return impl->isEqual(*other->impl);
            }
            Iterator& operator ++ ()
            {
                impl->next();
                return *this;
            }
            value_type& operator*() const 
            {
               return impl->get();
            }
            value_type* operator->() const
            {
               return &impl->get();
            }
        };
        Container();
        Container(const Container& other);
        ~Container();   

    virtual value_type& front() const=0;
    virtual value_type& back() const=0;
    virtual Iterator begin() const=0; // 
    ...
    };

Затем в вашем производном просто реализуем IteratorImpl:

class Linked_list:public Container 
{
protected:
    class IteratorImpl: public Container::IteratorImpl
    {
       ....
    };

public:
    Iterator begin() const { return new IteratorImpl(firstNode); }
    Iterator end() const { return new IteratorImpl(nodeAfterLastNode); }

...
};

Эти firstNode и nodeAfterLastNode - это только моя догадка - используйте все, что вам нужно для реализации интерфейса IteratorImpl...

Ответ 2

Вы должны определить const_value_type для представления const value_type и использовать его для возвращаемых значений переднего и заднего виртуальных методов. В качестве альтернативы вы можете отказаться от спецификаторов const для этих методов, потому что наличие типов ссылок не const-ссылок для методов const не имеет смысла.

Без каких-либо подробностей о классах это сложно сказать для остальных. Вы также можете взглянуть на ранние реализации STL: это очень хороший способ получить представление об этих темах.