1186 / 542 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
1

Метод класса возвращающий итератор

02.10.2011, 16:41. Показов 4179. Ответов 32
Метки нет (Все метки)

Не могу заставить метод класса возвращать итератор, помогите понять почему компилятор не разрешает это сделать:

Класс (методы возвращающие итераторы в самом низу)
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
class Students
{
    friend class StudentsIterator;
    struct ListItem
    {
        string fullname;
        string group;
        int year;
        int average;
        ListItem *Next;
    };
 
    ListItem *Head;
    ListItem *Tail;
    ListItem *Current; //указатель на текущий элемент
    int count; // всего элементов
 
public:
 
    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();}
 
    //методы для итераторов
    StudentsIterator* begin(){return Head;} //  cannot convert `Students::ListItem*' to `StudentsIterator*' in return
    StudentsIterator* end(){return NULL;} // ВСЁ ОК, КОМПИЛЯТОР НЕ РУГАЕТСЯ
};
Класс-итератор для него ,как видите есть перегруженный конструктор принимающий ListItem*:
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
class StudentsIterator
{
private:
    Students::ListItem* current;
 
public:
 
    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;
    }
 
    StudentsIterator* operator*()
    {
        return this;
    }
 
    operator bool()
    {
        return current!=0;
    }
 
};
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.10.2011, 16:41
Ответы с готовыми решениями:

Создать для класса виртуальный метод, возвращающий уникальный идентификатор класса
В курсаче по ООП сказано создать для класса виртуальный метод,возвращающий уникальный идентификатор...

Шаблон класса двусвязного списка, метод, возвращающий указатель
Пишу шаблон класса двусвязного списка. Всё в хедере. В классе присутствует структура item. Пытаюсь...

Итератор класса vector
Доброго времени суток. Попалась задача, в которой нужно определить итератор с проверкой выхода за...

Итератор для класса
Здравствуйте! Имеется определенный класс HashMap, необходимо определить для него...

32
Заблокирован
02.10.2011, 16:49 2
StudentsIterator begin(){ return Head; }
то что у тебя указатель на итератор возвращается я так понимаю ошибка
0
бжни
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
02.10.2011, 16:53 3
вы возвращает ListItem* (Head), хотя объявляете будто это StudentsIterator, что предлагаете компилятору делать?
второй вариант работает, так как NULL можно приводить к указателям любого типа
0
1186 / 542 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
02.10.2011, 17:01  [ТС] 4
LosAngeles, угу, а я какраз хочу чтобы функции класса begin() и end() возвращала итератор - это будет удобно для сортировки, печати и т.д. Я конечно могу сделать чтобы эта функция возвращала не итератор:
C++
1
2
        ListItem* begin(){return Head;} // Так нормально
        ListItem* end(){return NULL;} // компилируется
А потом в main делать так:
C++
1
2
3
Students obj;
StudentsIterator ite=obj.begin(); //Тоже всё ок, ite указывает на начало списка студентов
StudentsIterator ite_end=obj.end();//ite_end установлен в нуль (указывает на элемент ПОСЛЕ односвязного списка, те нуль)
Но это утомительно да и выглядит неуклюже когда я при печати списка создаю два новых итератора, печатаю список через них и больше их не использую, преподаватель наверняка прицепится насчёт этого.

Добавлено через 1 минуту
Цитата Сообщение от alex_x_x Посмотреть сообщение
вы возвращает ListItem* (Head), хотя объявляете будто это StudentsIterator, что предлагаете компилятору делать?
Воспользоваться конструктором копирования класса StudentsIterator перегруженого для получения ListItem* и вернуть мне этот итератор. Но это хочу я, как тогда по другому это сделать если компилятор так делать не хочет?
0
бжни
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
02.10.2011, 17:08 5
C++
1
StudentsIterator begin(){return StudentsIterator(Head);}
не ?
1
Заблокирован
02.10.2011, 17:13 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
class Students
{
    friend class StudentsIterator;
    struct ListItem
    {
        string fullname;
        string group;
        int year;
        int average;
        ListItem *Next;
    };
 
    ListItem *Head;
    ListItem *Tail;
    ListItem *Current; //указатель на текущий элемент
    int count; // всего элементов
 
public:
 
    class StudentsIterator
    {
    private:
        Students::ListItem* current;
 
    public:
 
        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;
        }
 
        StudentsIterator* operator*()
        {
            return this;
        }
 
        operator bool()
        {
            return current!=0;
        }
 
    };
 
    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(){}
 
    //методы для итераторов
    StudentsIterator begin(){return Head;} //  cannot convert `Students::ListItem*' to `StudentsIterator*' in return
    StudentsIterator end(){return NULL;} // ВСЁ ОК, КОМПИЛЯТОР НЕ РУГАЕТСЯ
};
1
бжни
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
02.10.2011, 17:18 7
В варианте LosAngeles просто неявно вызовется конструктор StudentsIterator(Students::ListItem* right)
0
1186 / 542 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
02.10.2011, 17:21  [ТС] 8
alex_x_x, не:
C++
1
2
3
In member function `StudentsIterator* Students::begin()':|
|80|error: invalid use of undefined type `struct StudentsIterator'|
|21|error: forward declaration of `struct StudentsIterator'|
Я так уже пробовал.
0
бжни
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
02.10.2011, 17:23 9
Цитата Сообщение от alex_x_x Посмотреть сообщение
StudentsIterator begin(){return StudentsIterator(Head);}
Цитата Сообщение от Gepar Посмотреть сообщение
StudentsIterator* Students::begin()
чтото не сходится
0
Заблокирован
02.10.2011, 17:23 10
Цитата Сообщение от Gepar Посмотреть сообщение
Я так уже пробовал.
в моём варианте этой проблемы нет
0
1186 / 542 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
02.10.2011, 17:37  [ТС] 11
Хотя нет, это я же написал что возвращаю указатель, а нужно просто возвращать StudentsIterator по версии alex_x_x, вот только вернуть получается просто StudentsIterator только если код class StudentsIterator находится внутри класса Students, иначе ругается, а код то у меня на самом деле большой ... как же его тогда подключить. Если перекидываю код класса-итератора в cpp файл, который компилирую совместно то компилятор ругается что не знает что такое ListItem , как сделать предварительное объявление тогда этой структуре ? (структура ListItem находится в классе Students).
LosAngeles, вообще чисто Ваш вариант тоже не работает (неявно не вызывается, опять же таки ругается почему-то, хотя должен и неявно вызываться как я изначально и планировал), но я не могу запихнуть код класса-итератора внутрь так как он большой, я ведь сюда запостил только то что касается проблемы чтобы не отпугивать и не запутывать Вас.

Добавлено через 8 минут
В общем у меня замкнутый круг: чтобы определить класс-итератор нужно чтобы был объявлен класс Студентов, а чтобы объявить методы begin/end класса Студенты нужно чтобы уже был объявлен итератор, как апофеоз всего этого:
сделав объявление в классе:
C++
1
2
    StudentsIterator begin();
    StudentsIterator end();
и потом сразу после определения класса-итератора внизу дописываю
C++
1
2
StudentsIterator Students:: begin(){return Head;}
StudentsIterator Students:: end(){return StudentsIterator(0);}
и получаю
Код
obj\Debug\main.o(.text+0x100)||In function `ZN8Students5beginEv':|
C:\c++\Projects\StudentsProject\Students.h|161|multiple definition of `Students::begin()'|
obj\Debug\students.o(.text+0x100):C:\c++\Projects\StudentsProject\Students.h|161|first defined here|
obj\Debug\main.o(.text+0x120)||In function `ZN8Students3endEv':|
C:\c++\Projects\StudentsProject\Students.h|162|multiple definition of `Students::end()'|
obj\Debug\students.o(.text+0x120):C:\c++\Projects\StudentsProject\Students.h|162|first defined here|
||=== Build finished: 4 errors, 0 warnings ===|
Те компилятор пишет что я определяя функцию переопределяю её (и первое и второе определение функции он пишет что это одна строка) О_о Всё, поздравьте меня, я запутался в ошибках компилятора окончательно.
0
Заблокирован
02.10.2011, 17:40 12
Цитата Сообщение от Gepar Посмотреть сообщение
но я не могу запихнуть код класса-итератора внутрь так как он большой
ctrl+copy - ctrl+paste и всё работает. И проблема циклических ссылок разрешена, а "большой код" как бы не является ни для кого проблемой
0
бжни
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
02.10.2011, 17:43 13
у вас ошибка в повторном определении функции begin()
0
1186 / 542 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
02.10.2011, 17:50  [ТС] 14
При попытках компилировать в VS я так понял из ошибок что строки в классе
C++
1
2
        StudentsIterator begin();
        StudentsIterator end();
оно воспринимает как объявление нового толи класса толи ещё чего-то, в общем как я понял мне нужно только как-то отделять класс-итератор в другой файл и компилировать вместе, посему нужно как-то обьявить существование структуры ListItem из класса Students - это должно быть решением всех моих проблем, но как это сделать?

Добавлено через 3 минуты
Цитата Сообщение от LosAngeles Посмотреть сообщение
ctrl+copy - ctrl+paste и всё работает. И проблема циклических ссылок разрешена, а "большой код" как бы не является ни для кого проблемой
Является, мой преподаватель любит "класивый код", для него это, как он выразился, "даставляет истинное наслаждение".

Цитата Сообщение от alex_x_x Посмотреть сообщение
у вас ошибка в повторном определении функции begin()
Где?
C++
1
2
StudentsIterator begin(); //обьявление в классе
StudentsIterator Students:: begin(){return Head;} //определение вне класса
объявление-определение, разве я где-то ошибся?
0
Заблокирован
02.10.2011, 17:59 15
Цитата Сообщение от Gepar Посмотреть сообщение
Является, мой преподаватель любит "класивый код", для него это, как он выразился, "даставляет истинное наслаждение".
где тут большой код то? глиста на две страницы это препод называет большим кодом? значит он некомпетентен, можно не обращать на него внимание
0
бжни
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
02.10.2011, 18:03 16
Цитата Сообщение от Gepar Посмотреть сообщение
объявление-определение, разве я где-то ошибся?
судя по ошибке он также объявлен внутри класса
0
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
02.10.2011, 18:03 17
Цитата Сообщение от Gepar Посмотреть сообщение
StudentsIterator begin(); //обьявление в классе StudentsIterator Students:: begin(){return Head;} //определение вне класса
объявление-определение, разве я где-то ошибся?
Вы возвращаете ListItem*, хотя говорите, что функция вернёт StudentsIterator
0
1186 / 542 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
02.10.2011, 18:06  [ТС] 18
LosAngeles, ну я же писал уже что здесь я привёл совсем маленький кусоче кода, все функции и методы не писал чтобы не запутывать, то что преподаватель с приколом это не поспоришь, и всё же то что я не знаю как сделать предварительное объявление для структуры ListItem из класса Students это моя вина, а не его, подскажите как это сделать. Я из-за этого если переношу свой код итератора в отдельный файл StudentsIterator.h не могу объяснить компилятору что же за структура такая ListItem и как с ней обращаться. Ну или же объясните мне пожалуйста где у меня два объявления функции begin() что тоже решит проблему.
Вообще я могу, если хотите, выложить код полностью в виде прикреплённого файла, если кому интересно и Вы хотите сами увидеть как ругается компилятор.
0
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
02.10.2011, 18:09 19
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
#include <iostream>
 
using namespace std;
 
template <typename T>
class List
{
    class item
    {
    public:
        T value;
        item * next;
        item * prev;
 
        item( T v ) : value ( v ), next(0), prev(0) {};
    };
 
    item * head,
         * tail;
 
public:
    class iterator
    {
        item * p;
 
    public:
        iterator( item * _p ) : p(_p){};
        iterator( const iterator &it ) : p( it.p ){};
 
        T & operator*(){ return p->value; };
 
        iterator operator++(int){
            if(p) p = p->next;
            return *this;
        };
 
        iterator operator--(int){
            if(p) p = p->prev;
            return *this;
        };
 
        bool operator==( const iterator &it ){ return p == it.p; };
        bool operator!=( const iterator &it ){ return p != it.p; };
 
        iterator & operator=( const iterator& it ){ p = it.p; return *this; }
    };
 
    List()
    {
        head = new item( 0 );
        tail = head;
    };
 
    ~List()
    {
        while( head )
        {
            item * old = head;
            head = head->next;
            delete old;
        }
    }
 
    void push_back( T v )
    {
        tail->value = v;
        tail->next = new item( 0 );
        tail->next->prev = tail;
        tail = tail->next;
    }
 
    void push_front( T v )
    {
        item * itm = new item( v );
        itm->next = head;
        head->prev = itm;
        head = itm;
    }
 
    iterator begin(){ return iterator( head ); };
    iterator end(){ return iterator( tail ); };
 
};
 
int main()
{
    List <char> lst;
 
    for( int i = 0; i < 8; i++ )
       lst.push_back( i + 'a' );
 
    for( int i = 8; i < 16; i++ )
       lst.push_front( i + 'a' );
 
    for( List<char>::iterator it = lst.begin(); it != lst.end(); it++ )
       cout << *it << ' ';
 
    cout << '\n';
 
    return 0;
}
Как-то так.
1
1186 / 542 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
02.10.2011, 18:11  [ТС] 20
Цитата Сообщение от alex_x_x Посмотреть сообщение
судя по ошибке он также объявлен внутри класса
ага, а vs 6.0 вообще пишет что begin объявлена 5(sic!) раз. Вот сами посмотрите прикреп. файл, если интересно.
У меня есть ещё хитрый план по переносу класса StudentsIterator в файл StudentsIterator.h, но ничего не получается: не могу уйнять компилятор насчёт того что такое ListItem.
Вложения
Тип файла: zip begin_end.zip (2.7 Кб, 7 просмотров)
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.10.2011, 18:11
Помогаю со студенческими работами здесь

Метод, возвращающий данные по имеющемуся ключу массива MAP
Исходный код: #include &lt;string&gt; #include &quot;map.h&quot; class Recipe{ protected: AnsiString...

Итератор и виртуальный метод
Есть задачка с гугла: #include &lt;iostream&gt; #include &lt;vector&gt; class A { public: A(int n...

Итератор для класса с массивом
Добрый день! Есть небольшая задачка.. необходимо написать класс для готовых комманд код ...

Итератор для класса-группы
Доброго времени суток. Нужна помощь. Выполняя лабы по методичке вновь возникла проблема с...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru