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

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 15, средняя оценка - 4.80
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,508
02.10.2011, 16:41     Метод класса возвращающий итератор #1
Не могу заставить метод класса возвращать итератор, помогите понять почему компилятор не разрешает это сделать:

Класс (методы возвращающие итераторы в самом низу)
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;
    }
 
};
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.10.2011, 16:41     Метод класса возвращающий итератор
Посмотрите здесь:

Итератор контейнера внутреннего класса шаблона C++
Итератор для своего контейнерного класса-списка C++
C++ Как описать метод класса? Как двумя способами описать инлайнируемый метод класса? Что такое this?
Как вынести метод возвращающий шаблонный класс в из hpp в cpp? C++
Метод, возвращающий данные по имеющемуся ключу массива MAP C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
LosAngeles
Заблокирован
02.10.2011, 16:49     Метод класса возвращающий итератор #2
StudentsIterator begin(){ return Head; }
то что у тебя указатель на итератор возвращается я так понимаю ошибка
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
02.10.2011, 16:53     Метод класса возвращающий итератор #3
вы возвращает ListItem* (Head), хотя объявляете будто это StudentsIterator, что предлагаете компилятору делать?
второй вариант работает, так как NULL можно приводить к указателям любого типа
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,508
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* и вернуть мне этот итератор. Но это хочу я, как тогда по другому это сделать если компилятор так делать не хочет?
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
02.10.2011, 17:08     Метод класса возвращающий итератор #5
C++
1
StudentsIterator begin(){return StudentsIterator(Head);}
не ?
LosAngeles
Заблокирован
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;} // ВСЁ ОК, КОМПИЛЯТОР НЕ РУГАЕТСЯ
};
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
02.10.2011, 17:18     Метод класса возвращающий итератор #7
В варианте LosAngeles просто неявно вызовется конструктор StudentsIterator(Students::ListItem* right)
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,508
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'|
Я так уже пробовал.
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
02.10.2011, 17:23     Метод класса возвращающий итератор #9
Цитата Сообщение от alex_x_x Посмотреть сообщение
StudentsIterator begin(){return StudentsIterator(Head);}
Цитата Сообщение от Gepar Посмотреть сообщение
StudentsIterator* Students::begin()
чтото не сходится
LosAngeles
Заблокирован
02.10.2011, 17:23     Метод класса возвращающий итератор #10
Цитата Сообщение от Gepar Посмотреть сообщение
Я так уже пробовал.
в моём варианте этой проблемы нет
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,508
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 ===|
Те компилятор пишет что я определяя функцию переопределяю её (и первое и второе определение функции он пишет что это одна строка) О_о Всё, поздравьте меня, я запутался в ошибках компилятора окончательно.
LosAngeles
Заблокирован
02.10.2011, 17:40     Метод класса возвращающий итератор #12
Цитата Сообщение от Gepar Посмотреть сообщение
но я не могу запихнуть код класса-итератора внутрь так как он большой
ctrl+copy - ctrl+paste и всё работает. И проблема циклических ссылок разрешена, а "большой код" как бы не является ни для кого проблемой
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
02.10.2011, 17:43     Метод класса возвращающий итератор #13
у вас ошибка в повторном определении функции begin()
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,508
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;} //определение вне класса
объявление-определение, разве я где-то ошибся?
LosAngeles
Заблокирован
02.10.2011, 17:59     Метод класса возвращающий итератор #15
Цитата Сообщение от Gepar Посмотреть сообщение
Является, мой преподаватель любит "класивый код", для него это, как он выразился, "даставляет истинное наслаждение".
где тут большой код то? глиста на две страницы это препод называет большим кодом? значит он некомпетентен, можно не обращать на него внимание
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
02.10.2011, 18:03     Метод класса возвращающий итератор #16
Цитата Сообщение от Gepar Посмотреть сообщение
объявление-определение, разве я где-то ошибся?
судя по ошибке он также объявлен внутри класса
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
02.10.2011, 18:03     Метод класса возвращающий итератор #17
Цитата Сообщение от Gepar Посмотреть сообщение
StudentsIterator begin(); //обьявление в классе StudentsIterator Students:: begin(){return Head;} //определение вне класса
объявление-определение, разве я где-то ошибся?
Вы возвращаете ListItem*, хотя говорите, что функция вернёт StudentsIterator
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,508
02.10.2011, 18:06  [ТС]     Метод класса возвращающий итератор #18
LosAngeles, ну я же писал уже что здесь я привёл совсем маленький кусоче кода, все функции и методы не писал чтобы не запутывать, то что преподаватель с приколом это не поспоришь, и всё же то что я не знаю как сделать предварительное объявление для структуры ListItem из класса Students это моя вина, а не его, подскажите как это сделать. Я из-за этого если переношу свой код итератора в отдельный файл StudentsIterator.h не могу объяснить компилятору что же за структура такая ListItem и как с ней обращаться. Ну или же объясните мне пожалуйста где у меня два объявления функции begin() что тоже решит проблему.
Вообще я могу, если хотите, выложить код полностью в виде прикреплённого файла, если кому интересно и Вы хотите сами увидеть как ругается компилятор.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 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;
}
Как-то так.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.10.2011, 18:11     Метод класса возвращающий итератор
Еще ссылки по теме:

C++ Итератор класса vector
Итератор внутри шаблонного класса C++
C++ Как передать в метод класса Menu указатель на метод дочернего класса?

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

Или воспользуйтесь поиском по форуму:
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,508
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 Кб, 6 просмотров)
Yandex
Объявления
02.10.2011, 18:11     Метод класса возвращающий итератор
Ответ Создать тему
Опции темы

Текущее время: 10:26. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru