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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как Вы обычно передаете stream разрабатывая парсер 
:(
    Опции темы
EvilsInterrupt
Дата 22.6.2013, 13:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



При разработке класса по работе с каким-либо форматом файла мы часто пользуемся стримами чтобы читать\писать из\в файл. До сих пор использую способ передачи базового класса стрима по ссылке в конструктор класса. Мне перестает нравиться по разным причинам и хочу узнать опыт других разработчиков, послушать их идиомы и методы.

Чтобы не было слишком излишне абстрактно возьмем задачу по разработке класса по работе с форматом "Super Format", ниже в коде приведены декларации заголовков. Также давайте напишем, который должен хранить и возвращать эти заголовки пользовательскому коду.

Код

namespace SuperFormat
{


struct FirstHeader
{
    uint8_t   magic;
    uint32_t  secondHeaderOffset;
};

struct SecondHeader
{
    uint16_t magic;
};


class SFImage
{
public:
    typedef  std::list<SecondHeader>  SecondHeaders_t;

public:
    const FirstHeader& first() const
    {
        return firstHeader;
    }

    const SecondHeaders_t& seconds() const
    {
        return secondHeaders;
    }

private:
    FirstHeader firstHeader;
    SecondHeaders_t secondHeaders;
};


} // namespace SuperFormat



Задача: Как-либо передать данные из\ в стрим во внутренние приватные члены firstHeader и secondHeaders. Другими словами как организовать работу со стримом, чтобы писать и записывать данные в эти приватные заголовки?

Пока вижу такие варианты:

Код

    // [1]
    SuperFormat::SFImage image;
    image.read( stream );
    image.first().magic = 0x84;
    image.write( stream );

    // [2]
    SuperFormat::SFImage image;
    read( image, stream );
    image.first().magic = 0x84;
    write( image, stream );

    // [3]
    SuperFormat::SFImage image(stream);
    image.read();
    image.first().magic = 0x84;
    image.write();

    // [4]
    SuperFormat::SFImage image;
    StreamPtr stream( new MemoryStream( 1000 * Mb) );
    image.setStream(stream);
    image.read();
    image.first().magic = 0x84;
    image.write();


Возможно Вы предложите еще, не стесняйтесь )

PM MAIL WWW ICQ Jabber   Вверх
mes
Дата 22.6.2013, 18:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

Репутация: 144
Всего: 250



Цитата(EvilsInterrupt @  22.6.2013,  12:57 Найти цитируемый пост)
Возможно Вы предложите еще, не стесняйтесь )


stream<<any_format(image)



--------------------
PM MAIL WWW   Вверх
EvilsInterrupt
Дата 22.6.2013, 19:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



Цитата(mes @  22.6.2013,  19:37 Найти цитируемый пост)
stream<<any_format(image)

Я отказался от такого варианта, т.к. менее читабелен чем read()/write() .
PM MAIL WWW ICQ Jabber   Вверх
volatile
Дата 22.6.2013, 20:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



1,
Цитата(EvilsInterrupt @  22.6.2013,  19:27 Найти цитируемый пост)
 менее читабелен чем read()/write() . 

как это менее читабелен?
Это же устоявшаяся практика в С++...

2.
Цитата(EvilsInterrupt @  22.6.2013,  13:57 Найти цитируемый пост)
    const FirstHeader& first() const

Цитата(EvilsInterrupt @  22.6.2013,  13:57 Найти цитируемый пост)
  image.first().magic = 0x84;

Как это вы пишете по константной ссылке?
И развивая мысль, если же возвращать не контантную ссылку, то смысла делать члены приватными - лишняя трата времени. все равно у всех полный доступ  smile 

3.
В общем в С++, есть устоявшаяся практика, делать глобальный оператор<<, и объявлять его дружественным (friend).
для доступа непосредственно к приватным членам.

Все остальные модификации  (по крайней мере для вашего примера) - суть одно и тоже, записанное разными способами.
Так зачем голову морочить себе и другим? 
Лучше идти обычным путем.


PM MAIL   Вверх
EvilsInterrupt
Дата 22.6.2013, 20:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



Цитата(volatile @  22.6.2013,  21:01 Найти цитируемый пост)
делать глобальный оператор<<, и объявлять его дружественным (friend).

Ввиду того  что пока у меня сформировалось свое собственное мнение по поводу использования "друзей", стараюсь этого не делать smile

Добавлено через 9 минут и 34 секунды
Цитата(volatile @  22.6.2013,  21:01 Найти цитируемый пост)
как это менее читабелен?
Это же устоявшаяся практика в С++...

Не совсем. Попадавшиеся мне проекты с применением набора библиотек POCO ни одного перегруженного оператора вывода\ввода. Правда это были проекты продуктов для reverse-engineer-ов и возможно это особенность мышления разработчиков. Но тем не менее не везде перегружается. К примеру в продукте компании где работаю не применяется
PM MAIL WWW ICQ Jabber   Вверх
volatile
Дата 22.6.2013, 21:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(EvilsInterrupt @  22.6.2013,  20:57 Найти цитируемый пост)
К примеру в продукте компании где работаю не применяется 

EvilsInterrupt, ну хорошо, делайте как принято у вас.
Принциаиальной выгоды от какого-то определенного способа нет.
Главное здесь - делать однообразно, а не придумывать каждый раз новое седло к старому велосипеду.  smile 




Это сообщение отредактировал(а) volatile - 22.6.2013, 21:22
PM MAIL   Вверх
EvilsInterrupt
Дата 22.6.2013, 21:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



Цитата(volatile @  22.6.2013,  22:21 Найти цитируемый пост)
ну хорошо, делайте как принято у вас.

Вопрос не в том делать мне или не делать как у меня принято в компании. Вопрос в другом.

Цитата(volatile @  22.6.2013,  22:21 Найти цитируемый пост)
Принциаиальной выгоды от какого-то определенного способа нет.

Есть. Столкнулся с тем, что мне стало сложно добавить новый код. У меня класс по работе с форматом принимает ссылку в конструкторе. Это приводит к тому, что после класс заполнить данными из другого стрима уже невозможно. Сейчас приходится рефакторить, вот если бы кто подсказал ранее!!! Да в процессе рефакторинга, сначала передавал стрим с помощью boost::shared_ptr, но это оказалось излишним. Вот и хочется узнать кто как делает, чтобы уменьшить количество лишних телодвижений.


PM MAIL WWW ICQ Jabber   Вверх
volatile
Дата 23.6.2013, 00:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(EvilsInterrupt @  22.6.2013,  21:33 Найти цитируемый пост)
Это приводит к тому, что после класс заполнить данными из другого стрима уже невозможно

Вот кстати, именно поэтому и не нужно изобретать велосипеды.  smile 


PM MAIL   Вверх
mes
Дата 23.6.2013, 03:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

Репутация: 144
Всего: 250



Цитата(EvilsInterrupt @  22.6.2013,  18:27 Найти цитируемый пост)
Я отказался от такого варианта, т.к. менее читабелен чем read()/write() . 

 smile Вы только разницу в синтаксисе заметили ? запишите написанное со скобками, сути не изменится.. 
подсказка: в моем примере трое участников вместо двух.. 

Цитата(EvilsInterrupt @  22.6.2013,  19:57 Найти цитируемый пост)
Код

делать глобальный оператор<<, и объявлять его дружественным (friend).
Ввиду того  что пока у меня сформировалось свое собственное мнение по поводу использования "друзей", стараюсь этого не делать 

нет прямой связи друзей с применением оператора.. Кстати чем так сильно отличается дружественная функция, от обычного метода ?!

Добавлено @ 03:24
Цитата(EvilsInterrupt @  22.6.2013,  20:33 Найти цитируемый пост)
 Это приводит к тому, что после класс заполнить данными из другого стрима уже невозможно. Сейчас приходится рефакторить, вот если бы кто подсказал ранее!!!


так вроде ж: http://forum.vingrad.ru/forum/topic-336639/unread-1.html  smile 


Это сообщение отредактировал(а) mes - 23.6.2013, 03:25


--------------------
PM MAIL WWW   Вверх
EvilsInterrupt
Дата 23.6.2013, 08:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



Цитата(mes @  23.6.2013,  04:14 Найти цитируемый пост)
так вроде ж: http://forum.vingrad.ru/forum/topic-336639/unread-1.html 

Это был формат PE, а я сейчас ковыряюсь с другим форматом, хоть и не хочется, но трудящиеся просят )

Цитата(mes @  23.6.2013,  04:14 Найти цитируемый пост)
Кстати чем так сильно отличается дружественная функция, от обычного метода ?!

Дело в том, что в public попадает то что очень редко будет меняться, а в привате автор кода имеет право переколбасить в любой момент наплевав на любое мнение. Если же сделать дружественную функцию, то в ней возникнет соблазн заюзать "по-быстрому" вон-ту функцию, но возникает лишняя зависимость, которую приходится учитывать если автор кода поменял сигнатуру исопользуемой функции или вообще удалил. Все-таки паблик на то и паблик, чтобы сказать пользователям класса "Вот методы, которые постараюсь менять в самых экстренных случаях"
PM MAIL WWW ICQ Jabber   Вверх
volatile
Дата 23.6.2013, 09:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(EvilsInterrupt @  23.6.2013,  08:51 Найти цитируемый пост)
 же сделать дружественную функцию, то в ней возникнет соблазн заюзать 

Ну запишите эту дружественную функцию в самом определении класа. (часто так и делают, кстати.)
И считайте что она не дружественная, а обычный метод.
Проблема, имхо, у вас в голове.
PM MAIL   Вверх
EvilsInterrupt
Дата 23.6.2013, 11:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



Цитата(volatile @  23.6.2013,  10:04 Найти цитируемый пост)
Проблема, имхо, у вас в голове. 

Тут Вы правы из-за желания написать хорошо иногда вхожу в ступор, вместо того чтобы просто написать и посмотреть как оно на практике будет выглядеть.

volatile, 
Попробую показать свое понимание дружеских функций, возможно вы увидите ошибки в рассуждениях и укажите на них. Сразу скажу, что опыт применения дружеских функций маленький и поэтому вполне возможно что вы все-таки ошибки увидите! Далее следуют мои мысли, а не цитаты из учебников, поэтому не следует говорить "где же вы такого по-набирались?".

Чисто технически пользовательский код не может видеть приватную часть другого класса. Но это можно организовать объявив в объявлении класса эту функцию дружественной. Получается вроде входит в namespace класса и в тоже время видит все его внутреннее состояние словно это метод класса. Однако при реализации такой функции нужны лишь часть а не весь функционал класса и получается своего рода "дыра". Во время написании такой функции программист отчетливо понимает как и что он пишет и зачем. Но проходит время, к этой функции обращается уже другой программист, который не знает всех деталей и нюансов класса. Который между прочим за это время тоже мог измениться. Для решения задачи из-за чего пришлось обратиться к модификации этой дружественной функции программист может обратиться к тому функционалу класса, который лучше всего не трогать! Да, спустя время юнит-тесты, интеграционные тесты или гневный пользователь все-таки ему скажет о неправильности его действий, но ведь это время!

По этой причине я делю код на интерфейсный и детали. Детали я изменяю как хочу и когда хочу, никто мне в этом ни указ, главное чтобы работало! А вот интерфейсный стараюсь не менять, иначе пользовательский код придется менять. Очень жалею что нету C++ конструкции, чтобы пометить какой-либо интерфейсный код меткой "depricated", разве что pragma для MSVS но это не портабельно!

Т.е. мое отношение к дружественным функциям такое, что лучше избегать их, иначе кто-то заюзает детали класса, а тебе потом собирать "артефакты" или помогать пофиксить код.
PM MAIL WWW ICQ Jabber   Вверх
mes
Дата 23.6.2013, 12:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

Репутация: 144
Всего: 250



Цитата(EvilsInterrupt @  23.6.2013,  07:51 Найти цитируемый пост)
Это был формат PE, а я сейчас ковыряюсь с другим форматом

и  smile  что это меняет ?!  в той теме были обобщенные советы, а не привязанные к формату.. 


Цитата(EvilsInterrupt @  23.6.2013,  10:40 Найти цитируемый пост)
Попробую показать свое понимание дружеских функций, возможно вы увидите ошибки в рассуждениях и укажите на них. 


Цитата(EvilsInterrupt @  23.6.2013,  10:40 Найти цитируемый пост)
Для решения задачи из-за чего пришлось обратиться к модификации этой дружественной функции программист может обратиться к тому функционалу класса, который лучше всего не трогать! 

все это относится и к методу... 

Цитата(EvilsInterrupt @  23.6.2013,  10:40 Найти цитируемый пост)
По этой причине я делю код на интерфейсный и детали. Детали я изменяю как хочу и когда хочу, никто мне в этом ни указ, главное чтобы работало! А вот интерфейсный стараюсь не менять, иначе пользовательский код придется менять. 

1. операторы относятся тоже к интерфейсу
2. где тут проблема с дружественными функциями ?!
3. оператор << может быть вполне и не дружественным.. 

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

Добавлено через 2 минуты и 31 секунду
Цитата(EvilsInterrupt @  23.6.2013,  10:40 Найти цитируемый пост)
Т.е. мое отношение к дружественным функциям такое, что лучше избегать их,

конечно, если от их применения ни красоты, ни эффективности не добавляется...

Добавлено через 4 минуты и 14 секунд
Цитата(volatile @  23.6.2013,  08:04 Найти цитируемый пост)
Ну запишите эту дружественную функцию в самом определении класа.

EvilsInterrupt, или сделайте метод вывода в поток, и заюзайте его в операторе - будут и овцы сыты и волки целы-  smile

Добавлено через 9 минут и 32 секунды
Цитата(EvilsInterrupt @  23.6.2013,  07:51 Найти цитируемый пост)
 Все-таки паблик на то и паблик, чтобы сказать пользователям класса "Вот методы, которые постараюсь менять в самых экстренных случаях"

1. public методы могут быть у private-классов.. smile.. 
2. интерфейс бывает и protected, и на него распространяются те же требования..

Добавлено через 11 минут и 48 секунд
Цитата(EvilsInterrupt @  23.6.2013,  07:51 Найти цитируемый пост)
, но возникает лишняя зависимость, 

это вобще отдельная тема, гораздо шире, чем публик-методы.. и кстати дружественные функции как раз и придуманы для уменьшения зависимостей и укрепления интерфейса  smile 


--------------------
PM MAIL WWW   Вверх
EvilsInterrupt
Дата 23.6.2013, 12:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



Цитата(mes @  23.6.2013,  13:36 Найти цитируемый пост)
вместо подобных рассуждений, думаю не плохо было бы задать себе вопрос, в чем же прелесть дружественных функций, и сразу станет понятно когда стоит ич применять, а когда нет..

Эти рассуждения как раз и были высказаны, чтобы ответить на этот вопрос. Я не однократно задавался этим вопросом и не понимаю в чем их крутость? Однако имеется только одно пояснение, которое я нашел зачем эти дружественные были введены в язык и оно написано в книге Страуструпа про Дизайн и Эволюцию языка.

Ок, спрошу у Вас: как вы понимаете в чем прелесть возможности объявить функцию\метод дружественной?
PM MAIL WWW ICQ Jabber   Вверх
mes
Дата 23.6.2013, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

Репутация: 144
Всего: 250



Цитата(EvilsInterrupt @  23.6.2013,  11:53 Найти цитируемый пост)
 в чем прелесть возможности объявить функцию\метод дружественной?

1. в том, что родной класс может быть не первым аргументом (this), уступив это место чужому
2. в том, что  можно связать два класса, без лишней публикации деталей.



--------------------
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.0617 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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