Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

Abstrakter Iterator из области С++

636  1 2 3 все
evgher постоялец04.07.12 16:10
evgher
04.07.12 16:10 
Последний раз изменено 04.07.12 16:12 (evgher)
Слудующая проблема
Изначально создаю обобщающий итератор, который определяет методы:\
В ответ на:

class AbstractIter{
public:
// constructor
AbstractIter(Element *pC);
bool operator!=(AbstractIter &ri);
Entry& operator*() ;
virtual AbstractIter& operator++( ) = 0; //prefix
virtual AbstractIter operator++(int) = 0; //postfix

Также создаю специализированный итератор
В ответ на:

class PostOrderIter : public AbstractIter{
public:
PostOrderIter();
virtual AbstractIter& operator++() ;
virtual AbstractIter operator++(int);
};

при компиляции выходит сообщение
В ответ на:

Error: Cannot return a value of abstract class BinTree<int>::AbstractIter.
Where: While instantiating "BinTree<int>::PostOrderIter::operator++(int)".

Как можно это заставить работать?
#1 
Simple Nothing is f*cked04.07.12 16:34
Simple
NEW 04.07.12 16:34 
в ответ evgher 04.07.12 16:10
По-моему, это плохая идея. Уж если хочется java like iterator, то и делай до конца, как в жабе: вместо перегрузки оператора сделай метод next.
#2 
Программист знакомое лицо04.07.12 17:37
NEW 04.07.12 17:37 
в ответ evgher 04.07.12 16:10
В ответ на:
Как можно это заставить работать?

Никак. Абстрактные классы нельзя инстанциировать :) Возвращай указатель/ссылку.
#3 
ThorV прохожий04.07.12 17:47
ThorV
NEW 04.07.12 17:47 
в ответ evgher 04.07.12 16:10
Вообще то итераторы предполагают использование template( хотя бы по Вашему типу Еntry), a шаблоны с virtual не дружат. Если хотите - делайте специализацию шаблонов, virtual тут не при чем.
А если хотите дальше заниматься глупостью, ибо иначе написанное выше назвать трудно, operator++(int) должен возвращать ссылку на объект, так что добавьте &, и будет Вам щастье:):)
#4 
evgher постоялец04.07.12 18:00
evgher
NEW 04.07.12 18:00 
в ответ Программист 04.07.12 17:37
Так дела в том что я инстанциирую не абстрактый класс. Смотри ниже
В ответ на:

BinTree<int>::PostOrderIter it; // not abstract!

Это как раз и ведёт к выше упомянутой выдаче на экран.
#5 
evgher постоялец04.07.12 18:09
evgher
NEW 04.07.12 18:09 
в ответ ThorV 04.07.12 17:47, Последний раз изменено 04.07.12 22:36 (evgher)
В ответ на:

operator++(int) должен возвращать ссылку на объект

Я тут с Вами не очень согласен. У постфикс-оператора это просто не возможно. Он возвращает копию объекта. Смотрите ниже пример из инета.
В ответ на:

Number& Number::operator++ ()
{
...
return *this;
}

Number Number::operator++ (int)
{
Number ans = *this;
++(*this); // or just call operator++()
return ans;
}

#6 
evgher постоялец04.07.12 18:19
evgher
NEW 04.07.12 18:19 
в ответ ThorV 04.07.12 17:47
В ответ на:

Вообще то итераторы предполагают использование template( хотя бы по Вашему типу Еntry), a шаблоны с virtual не дружат. Если хотите - делайте специализацию шаблонов, virtual тут не при чем.

Дело в том что идея состоит в том траверзировать контейнер с помощью разных итераторов в основу обобщающего итератора (абстрактного).
Т. е. все классы итераторы (специализированные или нет) это внутренние классы контейнера.
Самая главная проблема наверное и состоит в использовании template и virtual. Если использовать похожиую конструкцию без template, то всё вполне вероятно зароботает.
Но меня интересует именно тот факт - возможно это или нет.
#7 
Программист знакомое лицо04.07.12 18:25
NEW 04.07.12 18:25 
в ответ evgher 04.07.12 18:00

В ответ на:
Так дела в том что я инстанциирую не абстрактый класс.

Ага, только вот вернуть ты хочешь копию абстрактного класса :) А для того, чтобы вернуть копию абстрактного класса его (абстрактный класс) надо создать :) А этого делать нельзя :D
#8 
evgher постоялец04.07.12 18:55
evgher
NEW 04.07.12 18:55 
в ответ Программист 04.07.12 18:25
В ответ на:

Ага, только вот вернуть ты хочешь копию абстрактного класса

Вы правы. Если использовать только префикс-часть, то компайлер не выдаёт ошибок.
Получается что для постфикс инкремент в СИ++ этот вариант невозможен.
#9 
  scorpi_ завсегдатай04.07.12 18:59
NEW 04.07.12 18:59 
в ответ evgher 04.07.12 16:10
Это что за бред вообще? Курить стандарт С++ до полного прояснения. Чем не устроили обычные итераторы С++?
#10 
  scorpi_ завсегдатай04.07.12 19:01
NEW 04.07.12 19:01 
в ответ Simple 04.07.12 16:34
В ответ на:
Уж если хочется java like iterator, то и делай до конца, как в жабе: вместо перегрузки оператора сделай метод next

Не надо next. Он объединяет функции инкрементирования и возврата элемента, что делает многие алгоритмы более сложными.
#11 
evgher постоялец04.07.12 19:13
evgher
NEW 04.07.12 19:13 
в ответ scorpi_ 04.07.12 18:59, Последний раз изменено 04.07.12 20:03 (evgher)
Тут не о бреде речь. Хочу немного ознaкомиться с програмированием на СТЛ.
Некоторые вещи меня просто интересуют, т. к. у меня ещё не хватает навыков.
#12 
Simple Nothing is f*cked04.07.12 20:29
Simple
NEW 04.07.12 20:29 
в ответ evgher 04.07.12 19:13
stl весъ на шаблонах :)
#13 
Simple Nothing is f*cked04.07.12 20:30
Simple
NEW 04.07.12 20:30 
в ответ scorpi_ 04.07.12 19:01
зато он решает проблему автора :)
#14 
ThorV прохожий04.07.12 21:50
ThorV
NEW 04.07.12 21:50 
в ответ evgher 04.07.12 18:09
С какой стати постфикс-оператор невозможен???
Самое главное - итераторы реализуются шаблонами, иногда их специализируют, но не виртуальными классами. Это же на java, где кишки тянутся через весь язык до класса Object, зато нет шаблонов.
#15 
evgher постоялец04.07.12 22:25
evgher
NEW 04.07.12 22:25 
в ответ ThorV 04.07.12 21:50
Спасибо. Меня как раз возможность реализации и интересовала. Будем считать что вопрос исчерпан.
#16 
  scorpi_ завсегдатай06.07.12 07:00
NEW 06.07.12 07:00 
в ответ evgher 04.07.12 22:25
Не вполне. Курить здесь - http://www.boost.org/doc/libs/1_50_0/libs/iterator/doc/index.html
А вообще главное умение для программиста - умение гуглить. Например так: https://www.google.com/search?hl=en&q=c%2B%2B+iterator+site%3Astackoverflow.com
#17 
Программист знакомое лицо06.07.12 10:42
NEW 06.07.12 10:42 
в ответ ThorV 04.07.12 21:50
В ответ на:
Самое главное - итераторы реализуются шаблонами, иногда их специализируют, но не виртуальными классами.

Что-то говорит мне, что итераторы с шаблонами никак не связаны :) Просто потому что шаблон нужен для более высокого уровня абстракции, а итератор для перебора элементов.
Так например FindFirstFile и FindNextFile - вполне себе итератор, но шаблонами там и не пахнет :)
Очевидно, что реалицовывать итератор можно и без шаблонов. Например:
В ответ на:
class IIterator
{
public:
virtual void * Prev () = 0;
virtual void * Next () = 0;
virtual void * Value () = 0;
}
class CList : public IIterator
{
}

как видишь, итератор есть, а шаблонов нет :)
#18 
Murr патриот06.07.12 20:51
Murr
NEW 06.07.12 20:51 
в ответ Программист 06.07.12 10:42
итератор есть
-----
Где? Я не вижу ни одной возможности получить этот итератор...
#19 
ThorV прохожий07.07.12 08:13
ThorV
NEW 07.07.12 08:13 
в ответ Murr 06.07.12 20:51
+100:)
Как у Ходжи Насреддина: даже если 100 раз сказать халва, во рту слаще не станет...
#20 
ThorV прохожий07.07.12 08:15
ThorV
NEW 07.07.12 08:15 
в ответ ThorV 07.07.12 08:13
кстати, итератор, возвращающий void*, сам по себе весьма занятная конструкция
#21 
ThorV прохожий07.07.12 08:40
ThorV
NEW 07.07.12 08:40 
в ответ Программист 06.07.12 10:42
По поводу FindxxxFile рассмешил. Специализированная операция прохода по списку и итератор. Ню ню. А как без шаблонов реализовать универсальный итератор на c++, чтоб им можно было дереференсировать любые объекты, поделись пожалуйста опытом. reinterpret_cast<MySuperPuperClass>( void* ) рулит?
#22 
anly коренной житель07.07.12 17:56
anly
NEW 07.07.12 17:56 
в ответ ThorV 07.07.12 08:40
void* pUniversal;
слово даю на отсечение: итерирует всё!
Проклят нарушающий межи ближнего своего (Втор.27:17)
#23 
Simple Nothing is f*cked07.07.12 21:00
Simple
NEW 07.07.12 21:00 
в ответ anly 07.07.12 17:56
Но через жопу.
#24 
anly коренной житель08.07.12 00:52
anly
NEW 08.07.12 00:52 
в ответ Simple 07.07.12 21:00
через ж-пу разименование. а итерирование ничем не хуже.
Проклят нарушающий межи ближнего своего (Втор.27:17)
#25 
ThorV прохожий08.07.12 01:37
ThorV
NEW 08.07.12 01:37 
в ответ anly 08.07.12 00:52
А при итерации по массиву через что -жопу или тухес?
{}
#26 
anly коренной житель08.07.12 01:51
anly
NEW 08.07.12 01:51 
в ответ ThorV 08.07.12 01:37
а хочь чез что. разници то нет
Проклят нарушающий межи ближнего своего (Втор.27:17)
#27 
Программист знакомое лицо08.07.12 13:21
NEW 08.07.12 13:21 
в ответ Murr 06.07.12 20:51
В ответ на:
Где? Я не вижу ни одной возможности получить этот итератор...

Не понял, в чем проблема?
В ответ на:
class CList : public IIterator
{
public:
IIterator * GetIterator () { return this; }
}

#28 
Murr патриот08.07.12 13:25
Murr
NEW 08.07.12 13:25 
в ответ Программист 08.07.12 13:21
И что? Оно работает? Или все же абстрактный класс не инстанцируется?
#29 
Программист знакомое лицо08.07.12 13:34
NEW 08.07.12 13:34 
в ответ ThorV 07.07.12 08:15
Задача итетатора - пройти по элементам списка.
В ответ на:
Ню ню. А как без шаблонов реализовать универсальный итератор на c++, чтоб им можно было дереференсировать любые объекты, поделись пожалуйста опытом. reinterpret_cast<MySuperPuperClass>( void* ) рулит?

Ну тогда уж dinamic_cast, чтобы проверить на NULL :D
В любом случае, если не хочешь иметь дело с void *, то используй структуру классов. В чем проблема?
Кроме того, шаблонами хорошо описывать алгоритмы без привязки к типам данных, однако при использовании шаблонов ты все равно должен задать тип данных. Стл-список на void * накойже валинный как и на любом другом типе данных. А если у тебя есть структура классов, то ты легко можешь реализовать итератор на этих классах БЕЗ использования шаблонов.
Я не говорю о том насколько это хорошо или плохо (зачем изобретать велосипед, когда есть стл? :D), но все таки итераторы (по своему смыслу) вполне себе могут существовать и без шаблонов.
#30 
Программист знакомое лицо08.07.12 13:36
NEW 08.07.12 13:36 
в ответ Murr 08.07.12 13:25
Работает конечно :) Тут же возвращается указатель на абстрактный класс, а не сам абстрактный класс ;)
#31 
Murr патриот08.07.12 17:19
Murr
NEW 08.07.12 17:19 
в ответ Программист 08.07.12 13:36
Тут же возвращается указатель на
-----
Это Я, разумеется, вижу...
Чего Я не вижу - где инстанцируется то, что должно быть возвращено...
Ну и, должно быть очевидно, что писать руками имплементацию итератора каждый раз нет никакого желания...
#32 
  scorpi_ завсегдатай08.07.12 19:30
NEW 08.07.12 19:30 
в ответ Murr 08.07.12 17:19
В ответ на:
Чего Я не вижу - где инстанцируется то, что должно быть возвращено...

return this; там стоит. Это конечно дебилизм - приравнивать контейнер к итератору, но инстанция там есть.
В ответ на:
Ну и, должно быть очевидно, что писать руками имплементацию итератора каждый раз нет никакого желания...

Это было очевидно Абрахамсу уже 10 лет назад, почему он и написал итератор адаптор. На который я выше давал ссылку.
#33 
Murr патриот08.07.12 20:17
Murr
NEW 08.07.12 20:17 
в ответ scorpi_ 08.07.12 19:30
return this; там стоит.
------
Это Я вижу.
Я не вижу имплементации абстрактных методов. Писать их нет желания, а без них этот this бессмысленнен.
я выше давал ссылку
-----
Это не совсем ко мне - это к изобретателям сложных имплементаций давно наработанных решений.
#34 
ThorV прохожий08.07.12 21:23
ThorV
NEW 08.07.12 21:23 
в ответ Программист 08.07.12 13:34
>>Задача итетатора - пройти по элементам списка.
Задача итератора - пройтись по ЛЮБОМУ контейнеру, включая вектор и массив
>>Ну тогда уж dinamic_cast, чтобы проверить на NULL :D
А если у класса нет виртуальных функций, то компилятор шлет такому dynamic_cast большой пианэрский привет
>>В любом случае, если не хочешь иметь дело с void *, то используй структуру классов. В чем проблема?
Извини конечно, но какого ...уя использовать малопривлекательное решение от Явы? Как быть со встроенными типами? Писать оболочки вокруг int/char/float?
#35 
anly коренной житель08.07.12 22:30
anly
NEW 08.07.12 22:30 
в ответ ThorV 08.07.12 21:23
В ответ на:
Задача итератора - пройтись по ЛЮБОМУ контейнеру, включая вектор и массив
мне лично совершенно не понятно ЗАЧЕМ нужна такая вот универсальность?
Универсальность чаще всего идет в конфликте с производительностью или требуемым рессурсам.
Наоборот: каждому контейнеру свой итератор - специализированыый и быстрый и наиболее лучше подходящий.
Ну разве то ради забавы да спортивного интереса...
Проклят нарушающий межи ближнего своего (Втор.27:17)
#36 
ThorV прохожий08.07.12 23:45
ThorV
NEW 08.07.12 23:45 
в ответ anly 08.07.12 22:30
Интерфейс итераторов STL и с++-98 абсолютно универсален и на производительность влияет только реализация. Не нужна универсальность - на кой тогда нужны итераторы вообще? Пиши от руки списки, деревья и прочая, и будет тебе щастье.
#37 
anly коренной житель09.07.12 00:40
anly
NEW 09.07.12 00:40 
в ответ ThorV 08.07.12 23:45
В ответ на:
на кой тогда нужны итераторы вообще?
а чем итерировать без них то?
В ответ на:
Интерфейс итераторов STL и с++-98 абсолютно универсален
как раз там несколько специализированных итераторов для разных контейнеров.
к примеру vector::iterator имеет operator+=(int N), и реализация его считай мгновенная
а list::iterator такового не имеет, в виду того что реализовать его мгновенно (т.е. без перебора N раз) невозможно.
Проклят нарушающий межи ближнего своего (Втор.27:17)
#38 
  scorpi_ завсегдатай09.07.12 01:26
NEW 09.07.12 01:26 
в ответ anly 09.07.12 00:40
В ответ на:
к примеру vector::iterator имеет operator+=(int N), и реализация его считай мгновенная
а list::iterator такового не имеет, в виду того что реализовать его мгновенно (т.е. без перебора N раз) невозможно.

Ну да, лучше как в жабе, где список возвращает итератор случайного доступа...
#39 
  abubakr прохожий09.07.12 07:55
NEW 09.07.12 07:55 
в ответ anly 09.07.12 00:40
В ответ на:

как раз там несколько специализированных итераторов для разных контейнеров.
к примеру vector::iterator имеет operator+=(int N), и реализация его считай мгновенная
а list::iterator такового не имеет, в виду того что реализовать его мгновенно (т.е. без перебора N раз) невозможно.

Вы наверное имели ввиду operator++.
'Мгновенная' реализация, т.е. О(1), заслуга вовсе не итератора, а структуры данных, выбранной для реализации вектора.
Советую немного почитать про STL.
#40 
Программист знакомое лицо09.07.12 10:45
NEW 09.07.12 10:45 
в ответ Murr 08.07.12 17:19
В ответ на:
Чего Я не вижу - где инстанцируется то, что должно быть возвращено...

Ты уж прости меня, но писать всю эту требуху я не буду :) Ибо не смысла :D
В ответ на:
Ну и, должно быть очевидно, что писать руками имплементацию итератора каждый раз нет никакого желания...

кэп! :)
#41 
Программист знакомое лицо09.07.12 10:58
NEW 09.07.12 10:58 
в ответ ThorV 08.07.12 21:23
В ответ на:
Задача итератора - пройтись по ЛЮБОМУ контейнеру, включая вектор и массив

Задача (прикладная) пройтись по элементам конкретного контейнера, о котором известно ВСЕ уже на стадии написания кода.
А "пройтись по ЛЮБОМУ" контейнеру - это АБСТРАКЦИЯ, и разрешается, например, шаблонами. А можно эту абвстракцию разрешить и другим способом - например унаследовав все типы данных от CObject. Итератор будет, а шаблонов нет.
В ответ на:
А если у класса нет виртуальных функций, то компилятор шлет такому dynamic_cast большой пианэрский привет

Ну так можно ж сделать виртуальную функцию... в чем проблема?
В ответ на:
Извини конечно, но какого ...уя использовать малопривлекательное решение от Явы?

Ты что пытаешься мне доказать? Что стл рулит? :) Я это и так знаю и использую стл когда мне это нужно :) И своих итераторов не пишу :)
Но ведь это не означает, что нельзя написать итератор БЕЗ шаблона? Или как?
#42 
  abubakr прохожий09.07.12 11:32
NEW 09.07.12 11:32 
в ответ Программист 09.07.12 10:58
В ответ на:
А "пройтись по ЛЮБОМУ" контейнеру - это АБСТРАКЦИЯ, и разрешается, например, шаблонами. А можно эту абвстракцию разрешить и другим способом - например унаследовав все типы данных от CObject. Итератор будет, а шаблонов нет.

А как поступим с примитивными типами данных?
В ответ на:
Но ведь это не означает, что нельзя написать итератор БЕЗ шаблона? Или как?

Конечно можно. Но только в качестве примера, типа так делать ни в коем случае нинада :-)
#43 
Программист знакомое лицо09.07.12 12:09
NEW 09.07.12 12:09 
в ответ abubakr 09.07.12 11:32
В ответ на:
А как поступим с примитивными типами данных?

Уверен, что для примитивов тожно можено накалякать итератор :)
В ответ на:
Конечно можно.

Ну вот и славненько :)
Следовательно высказывание
В ответ на:
Вообще то итераторы предполагают использование template

опровергнуто.
ЧТД.
В ответ на:
Но только в качестве примера, типа так делать ни в коем случае нинада :-)

Это уже другая тема :D
#44 
anly коренной житель09.07.12 12:31
anly
NEW 09.07.12 12:31 
в ответ abubakr 09.07.12 07:55
нет, я имел ввиду +=
речь шла об универсальном итераторе для всех конрейнеров с любой структурой данных.
советую почитать тему.
Проклят нарушающий межи ближнего своего (Втор.27:17)
#45 
  abubakr прохожий09.07.12 12:39
NEW 09.07.12 12:39 
в ответ anly 09.07.12 12:31
насчет оператора я погорячился :-)
#46 
ThorV прохожий09.07.12 18:02
ThorV
NEW 09.07.12 18:02 
в ответ Программист 09.07.12 10:58, Последний раз изменено 09.07.12 18:18 (ThorV)
>>Задача (прикладная) пройтись по элементам конкретного контейнера, о котором известно ВСЕ уже на стадии написания кода.
Да ну? А как же быть с std::copy и практически всем <algorithm>?
>>Ну так можно ж сделать виртуальную функцию... в чем проблема?
Ни в чем, но зачем ? Ради dynamic_cast'а? Кстати, если ты уж озабочен производительностью, то dynamic_cast вещь довольно тяжеловесная, я уж не говорю, что :(
>>А можно эту абвстракцию разрешить и другим способом - например унаследовав все типы данных от CObject.
Привет из жабы... Осталось только как в жабе написать классы-оболочки вокруг встроенных типов( по другому и не получится )...
Самое главное, то что вы вдвоем впариваете, в лучшем случае может ( через анус и тухес ) работать со списками и деревьями, но пока что я не услышал ответа на вопрос: как итератор, не заточенный под конкретный тип дереференцируемого объекта, можно без шаблонов реализовать для векторов и массивов?
Короче, резюме:
Ты мне хочешь доказать, что умеешь ковырять в носу пяткой? Можно и так, согласен, но не надо пропагандировать это как здоровый образ жизни.
#47 
rahimov80 постоялец31.07.12 16:36
NEW 31.07.12 16:36 
в ответ ThorV 08.07.12 21:23, Последний раз изменено 31.07.12 16:38 (rahimov80)
В ответ на:
>>Задача итетатора - пройти по элементам списка.
Задача итератора - пройтись по ЛЮБОМУ контейнеру, включая вектор и массив

Это где вы такое определение видели? Вики говорит: "an iterator is an object that enables a programmer to traverse a container. "
В ответ на:
>>Ну тогда уж dinamic_cast, чтобы проверить на NULL :D
А если у класса нет виртуальных функций, то компилятор шлет такому dynamic_cast большой пианэрский привет
>>В любом случае, если не хочешь иметь дело с void *, то используй структуру классов. В чем проблема?
Извини конечно, но какого ...уя использовать малопривлекательное решение от Явы? Как быть со встроенными типами? Писать оболочки вокруг int/char/float?

Хотите задачу "из жизни". Есть контейнер, реализованный то ли как вектор, то ли лист. Он содержит пойнтеры на абстрактный CChannel, из который наследуется DVB-S Channel, DVB-T Channel, DVB-C Channel, etc (спутник, наземный сигнал, кабель, и т.д.)
По этому листу надо пройтись огромной кучей способов: последовательно от одного к другому, последовательно но пропустить не совпадающие каналы (для DVB-S должны совпадать bandwidth и поляризация - не суть важно), перепрыгнуть на величину графической страницы, перепрыгнуть но только на совпадающий канал, и т.д.
В этой задаче то, что предложил ТС и то что поддерживает "Программист" это то, что и нужно и ты не обойдешся здесь решениями из STL, и ни кто здесь не говорит об универсальном итераторе для встроенных типов, то есть "каждому овощу - свою корзину!"
#48 
Simple Nothing is f*cked31.07.12 16:49
Simple
NEW 31.07.12 16:49 
в ответ rahimov80 31.07.12 16:36
Первое впечатление: кривость дизайна. Если у CChannel есть интерфейс (а он должен быть), значит, информация о конкретных типах неважна. Следовательно, вполне достаточно стандартных итераторов.
#49 
rahimov80 постоялец31.07.12 17:17
NEW 31.07.12 17:17 
в ответ Simple 31.07.12 16:49
А никто и не говорит об конкретных типах: CChannel имеет какои нибудь bool IsCompatibly( CChannel& ) =0. Только второй итератор должен пропускать, те элементы которые ответят false, а первый итератор об этом и не спрашивает. А четверый ещё и должен подсчитывать, а сколько элементов он не пропустил.
#50 
Simple Nothing is f*cked31.07.12 22:44
Simple
NEW 31.07.12 22:44 
в ответ rahimov80 31.07.12 17:17
Это все можно сделать алгоритмами.
Впрочем, почему бы и нет?
#51 
1 2 3 все