![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 41 Всего: 154 |
Возникла следующая задача, есть сложная структура данных, элементы которой можно читать только последовательно, для этого случая идеально подходит паттерн "итератор". Вопрос в том, где его лучше описывать - внутри класса для доступа к которому он используется, или лучше его описать отдельно. Я понимаю, что оба решения примерно одинаковы, вопрос в том как будет более аккуратно, с учетом возможных последующих изменений.
|
|||
|
||||
| UnrealMan |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
Ну, лично мне бы не понравилось видеть определение одного большого класса (где много членов) внутри определения другого большого класса. А вот поместить внутрь определения класса только объявление вложенного класса - это можно. В случае ошибок в диагностическом сообщении компилятора будет хорошо видно, к чему относится вложенный класс.
Это сообщение отредактировал(а) UnrealMan - 17.12.2007, 15:02 |
|||
|
||||
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 41 Всего: 154 |
Я думал примерно так,
здесь может быть проблема если итератор использует защищенные методы и объявлен другом CBlockPacker-а, если я унаследую от CBlockPacker какой-то класс, то отношение дружбы потеряется, и итератор для производного класса работать перестанет. |
|||
|
||||
| UnrealMan |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
Наверное, шаблонными аргументами тут должно быть что-то другое. Некоторые компиляторы в сообщении об ошибке могут сослаться на CBlockIterator<....>, а не CBlockPacker<....>::Iterator. Вот я о чём. Что-то я не понял, где он перестанет работать. Приведи пример. Это сообщение отредактировал(а) UnrealMan - 17.12.2007, 16:06 |
|||
|
||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
описывать снаружи имеет смысл только в случае, если у тебя несколько классов с одинаковым интерфейсом доступа, для которых ты можешь использовать похожую реализацию итераторов.
насчет дружбы идея понятна, понятна и проблема. потому лучше их и не дружить. |
|||
|
||||
| Sartorius |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1568 Регистрация: 18.7.2006 Где: Ivory tower Репутация: 8 Всего: 37 |
ИМХО лучше помещать итератор в класс, с которым он будет работь. К чему плодить шаблоны?
|
|||
|
||||
| UnrealMan |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
А вот мне проблема не понятна. А как тогда обращаться к непубличным членам? Добавлено через 6 минут и 12 секунд У STL разные реализации. Добавлено через 11 минут и 54 секунды Например, в реализации STL от GNU, которая имеется у меня, итератор списка является невложенным классом. |
|||
|
||||
| JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
Подтверждаю: и у меня тоже. Так что... не факт, не факт. Я бы сказал так: если хватает публичных методов/полей класса для построения итератора - делаем внешний, если не хватает, то тут... не знаю, я склоняюсь ко внешнему, но, имхо, и так, и так сойдёт. |
|||
|
||||
| Lazin |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 41 Всего: 154 |
вопросов больше нет
это я малость ступил, я подумал что отношение дружбы не наследуется, поэтому тот-же шаблон не будет работать для производного класса(так как другом он объявлен в базовом), но никто не мешает мне объявить итератор другом и в производном. ps есть еще один вариант реализации итератора, это когда ф-ии для перебора элементов коллекции, находятся в классе коллекции. |
||||||
|
|||||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 53 Всего: 183 |
Не вижу связи. Вложенный класс точно так же не может обращаться к непубличным методам, если он не друг. И с шаблонами все то же, только параметры немного в другом месте описаны. Так что речь только об именах. Вложенный класс - меньше имен. Но. Если в дальнейшем возникнет необходимость в неполных объявлениях, на то вложенный клас без включения хедера не сошлешься, тогда как на внешний - элементарно. Резюме примерно такое: с точки зрения функуциональности - по барабану. Здесь нужно учитывать скорее публичность данного класса. Если это дело нужно сугубо локально, то вложенный класс - хорошее решение. Если речь идет о более широком использовании, лучше внешний клас. А чтобы крепче связать его с целевым контейнером и не громоздить многоэтажные имена, можно все засунуть в пространство имен. Важнее сделать нормальный интерфейс: раз уж называешь iterator, и то вести себя он должен как кошерный STL-итератор. Здесь может помочь boost::iterator_adapter - очень хорошая вешь, три четверти работы за тебя сделает. -------------------- ... |
|||
|
||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
дружба - очень сильная связь. надо иметь достаточно оснований для связи посредством дружбы. именно по этой причине дружба в С++ сделана нетранзитивной. в данном случае дружба дает только доступ к внутреннему устройству класса, что не менее эффективно достигается вложенным классом. а если итератор более общий, то класс, для которого он предназначен, будет иметь некий интерфейс для использования итераторами (или чем-то инициализировать итератор). здесь дружба и не понадобится. а в силу того что дружба не транзитивна, красиво и правильно использовать класс итератора с другими классами не выйдет. |
|||
|
||||
| UnrealMan |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
Earnest уже сказала, что по стандарту вложенный класс, в сравнении со всеми остальными классами, по умолчанию не имеет никаких привилегий касательно доступа к членам содержащего его класса. Хотя многие компиляторы это положение стандарта игнорируют и позволяют свободно обращаться к членам класса из его вложенного класса.
Что ещё за транзитивность дружбы такая? Это сообщение отредактировал(а) UnrealMan - 18.12.2007, 22:41 |
||||
|
|||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
не транзитивность. это означает, что если A дружит с B, а B дружит с C, то это не означает, что А дружит с С |
|||
|
||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
Согласен, я был неправ. |
|||
|
||||
| chipset |
|
||||||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4071 Регистрация: 11.1.2003 Где: Seattle, US Репутация: 27 Всего: 165 |
ИМХО, тут больше подходит "stack." Что ты будешь делать я вызову *(iter+=2)?
Адназначна --------------------
|
||||||||
|
|||||||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |