Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проектирование итератора 
:(
    Опции темы
Lazin
  Дата 17.12.2007, 14:23 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Возникла следующая задача, есть сложная структура данных, элементы которой можно читать только последовательно, для этого случая идеально подходит паттерн "итератор". Вопрос в том, где его лучше описывать - внутри класса для доступа к которому он используется, или лучше его описать отдельно. Я понимаю, что оба решения примерно одинаковы, вопрос в том как будет более аккуратно, с учетом возможных последующих изменений.
Код

///итератор для доступа к данным хранящимся в объекте класса Block
///класс Block должен иметь семантику CBlockPacker-а
template <class Block>
class CBlockIterator
{
const Block & m_owner;

CBlockIterator(const Block &o) : m_owner(o)//конструктор получает ссылку на объект класса содержащий данные
{
}

//методы итератора используют методы CBlockPacker 
//для доступа к данным через параметр шаблона Block
};

//класс - содержащий данные
template <class Format, class Packer>
class CBlockPacker
{
//методы для доступа к данным:

    class Iterator//то-же самое что и в случае с CBlockIterator только без шаблонов
    {
         //....
    };
};

template<class Format, class Packer>
class CBlockFTPacker : public CBlockPacker<Format, Packer>
{
//....
};

PM MAIL Skype GTalk   Вверх
UnrealMan
Дата 17.12.2007, 15:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 27
Всего: 32



Ну, лично мне бы не понравилось видеть определение одного большого класса (где много членов) внутри определения другого большого класса. А вот поместить внутрь определения класса только объявление вложенного класса - это можно. В случае ошибок в диагностическом сообщении компилятора будет хорошо видно, к чему относится вложенный класс.

Это сообщение отредактировал(а) UnrealMan - 17.12.2007, 15:02
PM MAIL   Вверх
Lazin
Дата 17.12.2007, 15:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(UnrealMan @  17.12.2007,  15:01 Найти цитируемый пост)
А вот поместить внутрь определения класса только объявление вложенного класса - это можно. В случае ошибок в диагностическом сообщении компилятора будет хорошо видно, к чему относится вложенный класс.

Я думал примерно так, 
Код

.....
class CBlockPacker
{
//....
typdef CBlockIterator<CBlockPacker> Iterator;
};

здесь может быть проблема если итератор использует защищенные методы и объявлен другом CBlockPacker-а, если я унаследую от CBlockPacker какой-то класс, то отношение дружбы потеряется, и итератор для производного класса работать перестанет.
PM MAIL Skype GTalk   Вверх
UnrealMan
Дата 17.12.2007, 16:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 27
Всего: 32



Цитата(Lazin @  17.12.2007,  15:14 Найти цитируемый пост)
Я думал примерно так, 

Наверное, шаблонными аргументами тут должно быть что-то другое.
Некоторые компиляторы в сообщении об ошибке могут сослаться на CBlockIterator<....>, а не CBlockPacker<....>::Iterator. Вот я о чём.


Цитата(Lazin @  17.12.2007,  15:14 Найти цитируемый пост)
здесь может быть проблема если итератор использует защищенные методы и объявлен другом CBlockPacker-а, если я унаследую от CBlockPacker какой-то класс, то отношение дружбы потеряется, и итератор для производного класса работать перестанет. 

Что-то я не понял, где он перестанет работать. Приведи пример.

Это сообщение отредактировал(а) UnrealMan - 17.12.2007, 16:06
PM MAIL   Вверх
baldina
Дата 17.12.2007, 18:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



описывать снаружи имеет смысл только в случае, если у тебя несколько классов с одинаковым интерфейсом доступа, для которых ты можешь использовать похожую реализацию итераторов.
насчет дружбы идея понятна, понятна и проблема. потому лучше их и не дружить.
PM MAIL   Вверх
Sartorius
Дата 17.12.2007, 18:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1568
Регистрация: 18.7.2006
Где: Ivory tower

Репутация: 8
Всего: 37



 ИМХО лучше помещать итератор в класс, с которым он будет работь. К чему плодить шаблоны?  smile  Нда и в STL такая реализация (чем не пример для подражания)
PM MAIL ICQ   Вверх
UnrealMan
Дата 17.12.2007, 18:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 27
Всего: 32



Цитата(baldina @  17.12.2007,  18:22 Найти цитируемый пост)
насчет дружбы идея понятна, понятна и проблема.

А вот мне проблема не понятна.

Цитата(baldina @  17.12.2007,  18:22 Найти цитируемый пост)
потому лучше их и не дружить. 

А как тогда обращаться к непубличным членам?

Добавлено через 6 минут и 12 секунд
Цитата(Sartorius @  17.12.2007,  18:29 Найти цитируемый пост)
Нда и в STL такая реализация (чем не пример для подражания) 

У STL разные реализации.

Добавлено через 11 минут и 54 секунды
Например, в реализации STL от GNU, которая имеется у меня, итератор списка является невложенным классом.
PM MAIL   Вверх
JackYF
Дата 17.12.2007, 19:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Цитата(UnrealMan @  17.12.2007,  18:35 Найти цитируемый пост)
Например, в реализации STL от GNU, которая имеется у меня, итератор списка является невложенным классом. 

Подтверждаю: и у меня тоже.

Так что... не факт, не факт. Я бы сказал так: если хватает публичных методов/полей класса для построения итератора - делаем внешний, если не хватает, то тут... не знаю, я склоняюсь ко внешнему, но, имхо, и так, и так сойдёт.


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Lazin
Дата 18.12.2007, 09:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(UnrealMan @  17.12.2007,  15:01 Найти цитируемый пост)
Ну, лично мне бы не понравилось видеть определение одного большого класса (где много членов) внутри определения другого большого класса. 

Цитата(Sartorius @  17.12.2007,  18:29 Найти цитируемый пост)
ИМХО лучше помещать итератор в класс, с которым он будет работь. К чему плодить шаблоны?  smile  Нда и в STL такая реализация (чем не пример для подражания) 

вопросов больше нет
Цитата(UnrealMan @  17.12.2007,  16:06 Найти цитируемый пост)
Что-то я не понял, где он перестанет работать. Приведи пример.

это я малость ступил, я подумал что отношение дружбы не наследуется, поэтому тот-же шаблон не будет работать для производного класса(так как другом он объявлен в базовом), но никто не мешает мне объявить итератор другом и в производном.
ps
есть еще один вариант реализации итератора, это когда ф-ии для перебора элементов коллекции, находятся в классе коллекции.
PM MAIL Skype GTalk   Вверх
Earnest
Дата 18.12.2007, 10:24 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Цитата(JackYF @  17.12.2007,  20:46 Найти цитируемый пост)
Я бы сказал так: если хватает публичных методов/полей класса для построения итератора - делаем внешний

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

Так что речь только об именах. Вложенный класс - меньше имен. Но. Если в дальнейшем возникнет необходимость в неполных объявлениях, на то вложенный клас без включения хедера не сошлешься, тогда как на внешний - элементарно.
Резюме примерно такое: с точки зрения функуциональности - по барабану. Здесь нужно учитывать скорее публичность данного класса. Если это дело нужно сугубо локально, то вложенный класс - хорошее решение. Если речь идет о более широком использовании, лучше внешний клас. А чтобы крепче связать его с целевым контейнером и не громоздить многоэтажные имена, можно все засунуть в пространство имен.

Важнее сделать нормальный интерфейс: раз уж называешь iterator, и то вести себя он должен как кошерный STL-итератор. Здесь может помочь boost::iterator_adapter - очень хорошая вешь, три четверти работы за тебя сделает.



--------------------
...
PM   Вверх
baldina
Дата 18.12.2007, 16:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(UnrealMan @ 17.12.2007,  18:35)
Цитата(baldina @  17.12.2007,  18:22 Найти цитируемый пост)
насчет дружбы идея понятна, понятна и проблема.

А вот мне проблема не понятна.

Цитата(baldina @  17.12.2007,  18:22 Найти цитируемый пост)
потому лучше их и не дружить. 

А как тогда обращаться к непубличным членам?

дружба - очень сильная связь. надо иметь достаточно оснований для связи посредством дружбы. именно по этой причине дружба в С++ сделана нетранзитивной. в данном случае дружба дает только доступ к внутреннему устройству класса, что не менее эффективно достигается вложенным классом. а если итератор более общий, то класс, для которого он предназначен, будет иметь некий интерфейс для использования итераторами (или чем-то инициализировать итератор). здесь дружба и не понадобится. а в силу того что дружба не транзитивна, красиво и правильно использовать класс итератора с другими классами не выйдет.
PM MAIL   Вверх
UnrealMan
Дата 18.12.2007, 22:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 27
Всего: 32



Цитата(baldina @  18.12.2007,  16:10 Найти цитируемый пост)
в данном случае дружба дает только доступ к внутреннему устройству класса, что не менее эффективно достигается вложенным классом.

Earnest уже сказала, что по стандарту вложенный класс, в сравнении со всеми остальными классами, по умолчанию не имеет никаких привилегий касательно доступа к членам содержащего его класса. Хотя многие компиляторы это положение стандарта игнорируют и позволяют свободно обращаться к членам класса из его вложенного класса.

Цитата(baldina @  18.12.2007,  16:10 Найти цитируемый пост)
дружба - очень сильная связь. надо иметь достаточно оснований для связи посредством дружбы. именно по этой причине дружба в С++ сделана нетранзитивной.

Что ещё за транзитивность дружбы такая?

Это сообщение отредактировал(а) UnrealMan - 18.12.2007, 22:41
PM MAIL   Вверх
baldina
Дата 18.12.2007, 22:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата

Что ещё за транзитивность дружбы такая?


не транзитивность.
это означает, что если A дружит с B, а B дружит с C, то это не означает, что А дружит с С
PM MAIL   Вверх
baldina
Дата 18.12.2007, 23:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(UnrealMan @ 18.12.2007,  22:39)
Цитата(baldina @  18.12.2007,  16:10 Найти цитируемый пост)
в данном случае дружба дает только доступ к внутреннему устройству класса, что не менее эффективно достигается вложенным классом.

Earnest уже сказала, что по стандарту вложенный класс, в сравнении со всеми остальными классами, по умолчанию не имеет никаких привилегий касательно доступа к членам содержащего его класса. Хотя многие компиляторы это положение стандарта игнорируют и позволяют свободно обращаться к членам класса из его вложенного класса.

Согласен, я был неправ.
PM MAIL   Вверх
chipset
Дата 19.12.2007, 08:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4071
Регистрация: 11.1.2003
Где: Seattle, US

Репутация: 27
Всего: 165



Цитата(Lazin @  17.12.2007,  04:23 Найти цитируемый пост)
элементы которой можно читать только последовательно, для этого случая идеально подходит паттерн "итератор".

ИМХО, тут больше подходит "stack." Что ты будешь делать я вызову *(iter+=2)?

Цитата(Earnest @  18.12.2007,  00:24 Найти цитируемый пост)
Резюме примерно такое: с точки зрения функуциональности - по барабану. 


Цитата(Earnest @  18.12.2007,  00:24 Найти цитируемый пост)
Важнее сделать нормальный интерфейс: раз уж называешь iterator, и то вести себя он должен как кошерный STL-итератор. Здесь может помочь boost::iterator_adapter - очень хорошая вешь, три четверти работы за тебя сделает.

Адназначна  smile 


--------------------
Цитата(Jimi Hendrix)
Well, I stand up next to a mountain
And I chop it down with the edge of my hand
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0740 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.