Полиморфизм и итерация по пользовательских контейнерах. Начнем? Имеется пользовательский контейнер по принципу linked list. Связанные между собой узлы. Стоит задача: подключить к нему итератор. Класс итератора структуры я наследую от двунаправленного итератора по узлам. Идея моя в том, чтобы переопределить операторы * и -> таким образом, чтобы они возвращали не конкретный итерируемый узел дерева, а данные, которые хранятся в узле. Иными словами - завуалировать использование структуры узлов и полностью скрыть их от внешнего использования. Ясное дело, попросту переопределить оператор мне не разрешают, в виду конфликта типов. template class MyIterator : std::iterator > {}; MyIterator подтягивает из std::iterator определенные в нем операторы (* и ->), которые возвращают тип MyQueueNode (что логично, ведь для отслеживания связей между узлами нужно итерироватся по самих узлах а не по данных, которые в них хранятся). Мне же нужно написать для MyIterator операторы (* и ->), которые будут возвращать тип T, на что компилятор говорит "прости, бро, конфликт возвращаемых типов". Если итерироваться напрямую по данных, то как в таком случае реализовать ++ и -- ? Быть может есть способ обойти наследование операторов, и прописать новые, игнорируя родительские? Да и вообще идеи интересно послушать по этому поводу.
Конечно, есть способ обойти это ограничение! Вам нужно переопределить операторы * и -> не в классе MyIterator, а в самом пользовательском контейнере, чтобы они возвращали не узел, а данные, которые хранятся в узле.
Вот пример кода:
template <typename T> class MyQueue { private: struct MyQueueNode { T data; MyQueueNode* next; }; MyQueueNode* head; MyQueueNode* tail; public: MyQueue() : head(nullptr), tail(nullptr) {} // Другие методы для добавления и удаления элементов class MyIterator { private: MyQueueNode* current; public: MyIterator(MyQueueNode* node) : current(node) {} T& operator*() { return current->data; } T* operator->() { return ¤t->data; } // Другие методы и операторы ++ и -- }; MyIterator begin() { return MyIterator(head); } MyIterator end() { return MyIterator(nullptr); } };
Теперь, когда вы используете итератор в цикле, вы будете получать доступ к данным в узлах, а не к самим узлам.
Надеюсь, что это поможет вам реализовать вашу задачу! Если у вас есть еще вопросы, не стесняйтесь задавать.
Конечно, есть способ обойти это ограничение! Вам нужно переопределить операторы * и -> не в классе MyIterator, а в самом пользовательском контейнере, чтобы они возвращали не узел, а данные, которые хранятся в узле.
Вот пример кода:
template <typename T>class MyQueue {
private:
struct MyQueueNode {
T data;
MyQueueNode* next;
};
MyQueueNode* head;
MyQueueNode* tail;
public:
MyQueue() : head(nullptr), tail(nullptr) {}
// Другие методы для добавления и удаления элементов
class MyIterator {
private:
MyQueueNode* current;
public:
MyIterator(MyQueueNode* node) : current(node) {}
T& operator*() {
return current->data;
}
T* operator->() {
return ¤t->data;
}
// Другие методы и операторы ++ и --
};
MyIterator begin() {
return MyIterator(head);
}
MyIterator end() {
return MyIterator(nullptr);
}
};
Теперь, когда вы используете итератор в цикле, вы будете получать доступ к данным в узлах, а не к самим узлам.
Надеюсь, что это поможет вам реализовать вашу задачу! Если у вас есть еще вопросы, не стесняйтесь задавать.