Пожалуйста, опубликуйте полный пример, показывающий проблему в будущем. Я предполагаю, что ошибка, с которой вы сталкиваетесь, выглядит примерно так: (https://wandbox.org/permlink/PKop4WMbpuygHoes)
prog.cc:73:19: error: cannot allocate an object of abstract type 'BaseIterator'
73 | for(auto&& i: a) {
| ^
prog.cc:3:7: note: because the following virtual functions are pure within 'BaseIterator':
3 | class BaseIterator
| ^~~~~~~~~~~~
prog.cc:19:27: note: 'virtual BaseIterator& BaseIterator::operator++()'
19 | virtual BaseIterator& operator++() = 0;
| ^~~~~~~~
prog.cc:73:19: error: cannot declare variable '__for_begin ' to be of abstract type 'BaseIterator'
73 | for(auto&& i: a) {
| ^
prog.cc:73:19: error: cannot allocate an object of abstract type 'BaseIterator'
prog.cc:73:19: error: cannot declare variable '__for_end ' to be of abstract type 'BaseIterator'
Проблема очевидна, поскольку цикл for пытается присвоить возвращаемое значение begin()
локальным переменным, которые он может 't.
C ++ не является Java. Цикл for для диапазона либо вызывает функции-члены begin
/ end
, либо вызывает свободные функции, поэтому интерфейс для получения итератора не требуется. Класс должен реализовывать только эти функции, и будет работать диапазон, основанный на. Кроме того, наличие operator!=
в базовом классе позволяет сравнивать два итератора разных подтипов. Чтобы проверить это, вам нужно использовать dynamic_cast
чтобы проверить типы. Вам также нужно уменьшить аргумент в реализации, который явно не является хорошим дизайном.
Наследование не так заметно для подобных проблем в C ++, и универсальный код с использованием шаблонов предпочтителенНапример, в STL. Все алгоритмы будут работать с совместимым итератором без наследования, поскольку тип итератора является шаблономrameter.
Ниже приведен пример использования простого класса Range в качестве контейнера для итератора: #include
struct Range;
struct Iterator {
Range const* r;
int current;
Iterator(Range const* x, int c) : r(x), current(c) {}
Iterator& operator++() {
++current;
return *this;
}
int const& operator*() const {
return current;
}
};
bool operator==(Iterator const& x, Iterator const& y) {
return x.current == y.current;
}
bool operator!=(Iterator const& x, Iterator const& y) {
return !(x == y);
}
struct Range {
int min;
int max;
Iterator begin() const {
return Iterator(this, min);
}
Iterator end() const {
return Iterator(this, max+1);
}
};
int main() {
Range r{-5, 5};
for(auto&& i: r) {
std::cout << i << std::endl;
}
}
Это упрощенный и неполный пример, демонстрирующий, как заставить его работать сдиапазон для цикла. Если вы хотите реализовать итераторы, соответствующие итераторам в стандартной библиотеке, вам нужно добавить несколько функций-членов и typedefs. Должно быть много информации о том, как написать эти итераторы.
PS: Если вы решите использовать Java-подобный подход с интерфейсами, не забудьте предоставить своим интерфейсам (открытый или защищенный) виртуальный деструктор иобъявите конструкторы копирования как delete
, чтобы предотвратить нарезку объектов.