Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 73, средняя оценка - 4.92
Gepar
1175 / 531 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
#1

Собственный класс-итератор - C++

01.10.2011, 20:51. Просмотров 9849. Ответов 6
Метки нет (Все метки)

Создаю класс-итератор для класса Студенты.
Сам класс студенты:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#ifndef STUDENTS_H
#define STUDENTS_H
 
#include <string>
using std::string;
 
#include <iostream>
using std::cout;
using std::cerr;
 
#include <iomanip>
using std::setw;
 
#include <stdexcept>
using std::out_of_range;
 
class Students
{
    friend class StudentsIterator;
    struct ListItem
    {
        string fullname;
        string group;
        int year;
        int average;
        ListItem *Next;
        ListItem(string name="",int y=0,int aver=0,string gr="",ListItem* next=0)
        {
            fullname=name;
            group=gr;
            average=(aver>=0 && aver<=100 ? aver : -1);
            year=(y>=1950 && y<=2012 ? y : -1);
 
            if(average==-1 || year==-1)
             throw Exception("wrong data");
            Next=next;
        }
    };
 
    ListItem *Head;
    ListItem *Tail;
    ListItem *Current; //указатель на текущий элемент
    int count; // всего элементов
 
public:
    class Exception
    {
        string str;
        public:
        Exception(string data) :str(data){};
        string what(){return str;}
    };
 
    Students(): Head(0), Tail(0), Current(0), count(0) {}
 
    Students(string data, int y, int a, string g)
    {
        Head=Tail=new ListItem(data,y,a,g);
        Current=0;
        count=1;
    }
 
    ~Students(){this->deleteAll();}
 
 
    void addToTail(string data, int y, int a, string g);
    void addToHead(string data, int y, int a, string g);
 
 
    void deleteFromHead(bool mode=1);//1 - с предупреждением(исключением) если список пуст
    void deleteFromTail();
    void deleteAll();
 
    void print();
 
    //for iterators
    ListItem* begin(){return Head;}
    ListItem* end(){return Tail;}
};
Класс-итератор для класса студенты:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
class StudentsIterator
{
    private:
    Students::ListItem* current;
 
    //функция для проверки что current инициализирован
    void correct(){if(current==0) throw Students::Exception("access denied");}
 
public:
 
    string first(){correct();return current->fullname;}
    string second(){correct();return current->group;}
    int third(){correct();return current->year;}
    int four(){correct();return current->average;}
 
    StudentsIterator() {current=0;}
 
    StudentsIterator(const Students &right)
    {
        *this=right;
    }
 
    StudentsIterator(Students::ListItem* right)
    {
        *this=right;
    }
 
 
    StudentsIterator* operator=(Students &right)
    {
        current=right.Current;
        return this;
    }
 
    //для указателей на элемент, например на начало или конец списка
    StudentsIterator* operator=(Students::ListItem* right)
    {
        current=right;
        return this;
    }
 
    Students::ListItem* operator++()
    {
        return (current=current->Next);
    }
 
    Students::ListItem* operator++(int)
    {
        Students::ListItem* temp=current;
        ++current;
        return temp;
    }
 
    Students::ListItem* operator*()
    {
        return current;
    }
 
};
 
#endif
Проблема заключается в перегрузке постфиксного оператора инкремента (operator++(int)) - почему-то при вызове из main я получаю вылет, компилятор предупреждений же никаких не выдаёт, но видать что-то же я сделал неправильно, но что именно? Почему я получаю вылет из программы (не моё исключение), может я как-то неправильно возвращаю указатель или ещё чего? Префиксный оператор ++ работает корректно.
Ну и если так есть какие комментарии по поводу улучшения реализации односвязного списка со студентами то тоже пишите.
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.10.2011, 20:51
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Собственный класс-итератор (C++):

Класс: как обратиться к методу производного класса через итератор на базовый класс? - C++
Есть абстрактный и два порожденных. Хочу создать например list&lt;Base*&gt; list1; затем добавляю себе в список: ...

Написать класс-итератор - C++
Здравствуйте, мне дали такое здание: написать класс-контейнер множество, состоящее из объектов произвольного типа. Методы класса...

Доработать класс Итератор - C++
1. Добавить в класс Iterator некоторые функции, аналогичные имеющимся (перегрузка предекремента и постдекремента, перегрузка -=, вычитание...

Класс итератор для стека - C++
Доброго времени суток! Обращаюсь к вам за помощью. Хоть сама в тему эту не совсем влилась, прошу гляньте код. Ругается, но я...

STL и собственный класс - C++
Подскажите, пожалуйста, как можно переопределить функцию STL для собственного класса. Например, push_front() или push_back() не работают...

Собственный класс итератора - C++
Добрый день! Пишу сейчас одну библиотеку (не использующею STL и другие библиотеки) и для контейнеров решил написать класс итератора: ...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
ForEveR
В астрале
Эксперт С++
7971 / 4733 / 321
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
01.10.2011, 21:27 #2
Gepar, Ну хоть разберитесь как итератор реализовывается... Операторы ++ должны возвращать объект итератора.

Пример итератора.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
template<class T>
class Iterator
{
public:
   Iterator(T* curr):current(curr)
   {
   }
   Iterator& operator =(const Iterator& other)
   {
       if (this != &other)
       {
           current = other.current;
       }
       return *this;
   }
   Iterator& operator ++()
   {
       ++current;
       return *this;
   }
   Iterator operator ++(int i)
   {
       Iterator tmp(current);
       ++current;
       return tmp;
   }
   T operator *()
   {
      return *current;
   }
   T* operator ->()
   {
      return current;
   }
private:
   T* current;
};
Gepar
1175 / 531 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
01.10.2011, 21:29  [ТС] #3
И ещё вопрос по итераторам:
Как эта перегрузка оператора сравнения в итераторе
C++
1
2
3
4
    bool operator==(StudentsIterator& right) const
    {
        return (current==right.current);
    }
Может компилироваться, ведь current у меня находится в private части !Я уже было собрался написать функцию для возврата const ссылки на current,но внезапно оказалось что код скомпилировался, но как так ? Ведь right это ссылка на StudentsIterator с PRIVATE элементом current, как же это тогда компилятор даёт к нему доступ здесь, когда в main не даёт (что вполне логично) ?
ForEveR
В астрале
Эксперт С++
7971 / 4733 / 321
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
01.10.2011, 21:55 #4
Сообщение было отмечено автором темы, экспертом или модератором как ответ
А вот простенький код контейнера и итератора + совместимость с STL алгоритмами.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include <iterator>
#include <iostream>
#include <algorithm>
#include <cstddef>
 
template<class T>
class Iterator;
 
template<class T>
class array
{
public:
   typedef Iterator<T> iterator;
   typedef size_t size_type;
   typedef T* pointer;
   typedef const T* const_pointer;
   typedef T& reference;
   typedef const T& const_reference;
   typedef T value_type;
   
   array():arr_(new T[0]), sz_(0)
   {
   }
   array(size_t sz):sz_(sz), arr_(new T[sz])
   {
      std::fill(arr_, arr_ + sz_, T());
   }
   array(const array& arr)
   {
      delete arr_;
      sz_ = arr.sz;
      arr_ = new T[sz_];
      std::copy(arr.arr_, arr.arr_ + sz_, arr_);
   }
   array& operator =(const array& arr)
   {
      array tmp(arr);
      swap(tmp);
      return *this;
   }
   ~array()
   {
      delete[] arr_;
   }
   Iterator<T> begin()
   {
      return Iterator<T>(arr_);
   }
   Iterator<T> end()
   {
      return Iterator<T>(arr_ + sz_);
   }
   T& operator [](size_t idx)
   {
      return arr_[idx];
   }
   const T& operator [](size_t idx) const
   {
      return arr_[idx];
   }
   size_t size() const
   {
      return sz_;
   }
private:
   void swap(array& first, array& second)
   {
      std::swap(first.arr_, second.arr_);
      std::swap(first.sz_, second.sz_);
   }
   T* arr_;
   size_t sz_;
};
 
template<class T>
class Iterator
{
public:
   typedef T value_type;
   typedef T* pointer;
   typedef T& reference;
   typedef std::forward_iterator_tag iterator_category;
   typedef ptrdiff_t difference_type;
   
   Iterator(T* curr):current(curr)
   {
   }
   Iterator& operator =(const Iterator& other)
   {
       if (this != &other)
       {
           current = other.current;
       }
       return *this;
   }
   Iterator& operator ++()
   {
       ++current;
       return *this;
   }
   Iterator operator ++(int i)
   {
       Iterator tmp(current);
       ++current;
       return tmp;
   }
   T& operator *()
   {
      return *current;
   }
   T* operator ->()
   {
      return current;
   }
   bool operator ==(const Iterator& other)
   {
      return current == other.current;
   }
   bool operator !=(const Iterator& other)
   {
      return !(*this == other);
   }
private:
   T* current;
};
 
int main()
{
   array<int> arr(5);
   for (array<int>::iterator iter = arr.begin(); iter != arr.end(); ++iter)
   {
      std::cout << *iter << std::endl;
   }
   for (array<int>::iterator iter = arr.begin(); iter != arr.end(); ++iter)
   {
      *iter = 5;
   }
   for (array<int>::iterator iter = arr.begin(); iter != arr.end(); ++iter)
   {
      std::cout << *iter << std::endl;
   }
   std::copy(arr.begin(), arr.end(), std::ostream_iterator<int>(std::cout, "\n"));
}
silent_1991
Эксперт С++
4963 / 3039 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
01.10.2011, 23:21 #5
Цитата Сообщение от Gepar Посмотреть сообщение
Как эта перегрузка оператора сравнения в итераторе ... Может компилироваться
Потому что operator== - метод класса, объектом которого является right. Этот класс, разумеется, имеет доступ к своим приватным полям, и не важно, что operator== вызывается из одного объекта и принимает ссылку на другой, метод будет иметь доступ к обоим этим объектам. Ведь строка
C++
1
return (current==right.current);
эквивалентна
C++
1
return ((*this).current==right.current);
, и по вашей логике (*this).current тоже не должно работать (прямой доступ к закрытому члену).
Gepar
1175 / 531 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
02.10.2011, 02:10  [ТС] #6
Цитата Сообщение от ForEveR Посмотреть сообщение
Gepar, Ну хоть разберитесь как итератор реализовывается... Операторы ++ должны возвращать объект итератора.
Исправил, спасибо, ещё немного доделаю и представлю на обозрение, буду благодарен если ещё раз покритикуете, ато эту лабу в отличии от тех заданий что я делал в последнее время, нужно будет сдавать.
metalion
Сообщений: n/a
16.12.2011, 13:28 #7
Новую тему решил не создавать, вопрос следующий:
Есть структура, созданная на основе паттерна компоновщик. Нужно обойти эту структуру итератором. Может кто привести готовое простенькое решение для понимая концепции?
Мои предположения:
3 вида итераторов(рекурсивный, пустой, обычный(к примеру для просмотра контейнера <vector>) ну и стек.+ необходим метод создания рекурсивных итераторов.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.12.2011, 13:28
Привет! Вот еще темы с ответами:

Реализуйте собственный класс строки - C++
Задание: Строка Реализуйте собственный класс строки для использования в языке C++. Класс должен поддерживать наиболее часто...

Реализовать двусвязный список (list), итератор (iterator) и константный итератор (сonst_iterator) для списка - C++
не могу понять что должно быть результатом. может подскажете примеры? пожалуйста. Задание: Реализовать двусвязный список (list),...

Map и собственный класс: GCC ругается - C++
Что я делаю не так? Мэйн: int main() { string s = &quot;abc&quot;; map&lt;string, ConfigSection&gt; sectionList; sectionList =...

Функция, дружественная классу, вложенному в шаблонный класс, или как написать итератор. - C++
Здравствуйте! Пишу аналог STL vector. Возникают следующие ошибки: source.cpp:11: error: expected initializer before ‘operator’ ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
16.12.2011, 13:28
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru