2013-08-11 2 views
3

У меня возник вопрос о реализации совместного интерфейса итератора.Оператор постфиксного абстрактного базового класса C++

Как обычная практика для оператора postix функция может выглядеть следующим образом:

IteratorClass operator ++(int) { 
    IteratorClass temp = *this; 

    //increment stuff 

    return temp 
} 

И большую часть времени, это прекрасно. В моем случае я пытаюсь реализовать 3 итератора для одного класса. Каждый итератор будет загружать локальный класс коллекции данными, но каждый производный итератор будет загружать его по-другому. Поскольку класс коллекции будет таким же, и весь код для операторов (постфикса/префикс ++/- *) будет такой же, я думал, что хороший способ осуществить это было бы наследование:

struct iterator { 
    protected: 
    Collection collection; 
    public: 
    operator++(int); 
    operator++; 
    operator--(int); 
    operator--; 

    virtual load() = 0; 

} 

struct iterator1 : public iterator { 
    virtual load() { custom load function } 
} 

struct iterator2 : public iterator { 
    virtual load() { custom load function } 
} 

Проблема - это постфиксные операторы ... Они пытаются создать объект абстрактного типа и затем возвращать его. Любые предложения об обходных решениях или изменениях структуры?

+0

Вам действительно нужно иметь постфиксный оператор, как правило, это плохая идея использовать их для итераторов. – Phil1970

ответ

4

Используйте CRTP idiom, чтобы базовый класс знал об окончательном классе. Например:

template<typename T> 
struct iterator_base { 
    public: 
    T operator++(int) { 
    T temp = static_cast<T&>(*this); 
    ++*this; 
    return temp; 
    } 
    T& operator++() { 
    // ++ mutation goes here 
    return *this; 
    } 
    // ... likewise for --, etc. 
}; 

struct iterator1: public iterator_base<iterator1> { 
    // ... custom load function 
}; 

Этот подход называется статический полиморфизм, и позволяет (в некоторых случаях), чтобы полностью отказаться от virtual и, следовательно, сделать ваши объекты меньше. Вы можете пропустить объявление load из базовых классов и позвонить T::load как static_cast<T&>(*this).load().

+0

Прохладный, спасибо за подсказку! Я попытался реализации, что вы сказали, и связано также и это почти там, но теперь им застрял на, ну, следующая ошибка .... «AVLTree <_K,_T> :: BinaryTreeTraversal <_D>» до «AVLTree <_K,_T> :: заказовМои» Нужна ли мне какая-то литье? После выполнения: struct InOrder: public Traversal kris

+0

@kris Какая строка ошибки? Вы правильно объявляли 'operator ++ (int)' и 'operator ++()' как возвращающие 'T' и' T & 'соответственно? – user4815162342

+0

Вот точный код, он терпит неудачу во второй строке. _D operator ++ (int) { _D temp = * this; ++ местный; температура возврата; } Редактировать: Это не форматирует красиво – kris

Смежные вопросы