![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| GKosh |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 30 Регистрация: 27.12.2005 Репутация: нет Всего: нет |
Необходимо было реализовать сериализацию для иерархии собственных классов, сделал так:
Базовый класс всей иерархии имеет динамический список структур вида struct PROPERTY { const char* sProperty; // имя переменной - члена класса void** pProperty; // указатель на переменную SERIA_TYPE Type; // метка типа переменной (int, float, string, object) }; по идее - это как бы карта свойств объекта, базовый класс реализует так же метод: void Register_Property (const char* a_name, void* a_pointer, SERIA_TYPE a_type) для заполнения этого списка указателями на переменные. Каждый класс иерархии в своем конструкторе регистрирует свои переменные этой функцией, после чего наследованные методы базового класса Serialize/Deserialize уже спокойно записывают, считывают заполненный список указателей. Таким образом практически вся реализация ser/deser находится только в базовом классе. Вопрос - может быть что-нибудь есть дурного в таком подходе, пока я его еще не отладил но у меня имеются некоторые сомнения в его надежности. Возможно есть проверенные методы о которых я, к сожалению, не в курсе. Заранее благодарен, Константин. |
|||
|
||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 53 Всего: 183 |
Конечно. Твой подход годится только для очень простых структур (где только независимые переменные). Да и то, а если это не-плоские классы? Или строки (не char[] а string)? Нельзя их тупо по адресу писать-читать. Пардон, строки у тебя предусмотрены... Однако все остальное - в силе. Представь, у тебя есть контейнер, где частью элемента являются ссылки на какие-то другие классы (которые тоже сериализуются). Но самое главное (ИМХО) - скрытое хранение адресов элементов класса где-то еще лишает его объекты семантики значений - или нужно потратить усилия, чтобы ее обеспечить. Неоправданное усложнение, по-моему. Сама по себе сериализация становится сложной, только когда начинаешь думать о поддержке версий. А так - чем проще, тем лучше. Мне кажется, в данном случае лучше подходить проще: сделать в базовом классе твоей иерархии метод Serialize (как в MFC) и переопределять его + написать хелперы для сериализации контейнеров, строк и простых типов. Здесь по крайней мере соблюдается единство места: все поведение класса локализовано и все изменения производятся в одном месте. Вроде есть еще boost::seriazlize, но сама не пользовалась. -------------------- ... |
|||
|
||||
| azesmcar |
|
||||||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Немало думал над этим, пока что (во всяком случае для меня) единственный приемлемый вариант был такой...это для серилизации некоторых структур...например есть функция которая должна записывать структуры и классы в файл...
Реализуем класс наподобие...
А функцуя WriteToFileStruct будет иметь следующий вид
Ничего более универсального придумать не смог...да вряд ли есть способ..если в классе есть динамическое выделение памяти |
||||||||
|
|||||||||
| Chaos A.D. |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 172 Регистрация: 16.1.2005 Где: 09 RUS Репутация: 6 Всего: 7 |
Давно не думал в этом направлении, так что могу спороть чушь... По-моему, если у тебя есть иерархия, и тебе просто нужно сделать её всю сериализуемой, то добавь в неё пару виртуальных функций типа "Писать" - "Читать", и все. Ну а указатели сделать умными, правда это не очень хорошо, придется модифицировать всю иерархию... С указателями я бы попытался отвертеться с помощью свойств - Специализирую шаблон для типа указателя, и для него сохраняю то, на что он указывает.
И не стоит заморачиваться с решением общего случая сериализации - лучше чем у Boost-а вряд-ли получится. В любом случае, у тебя в твоем примере каждый производный класс должен знать о том, что его будут сериализовать (я имею ввиду твой конструктор). Ну а так, перегружаешь функцию, и все. Если напрягает то, что класс должен знать о том, куда его пишут, сделай функцию, которая бы просто преобразовала объект в последовательность битов, и наоборот. А всё остальное выноси из класса. Можно так-же заюзать паттерн Factory, производящий объекты из строки. Страуструп в своей книге пару раз упомянает объектный ввод/вывод - Тоже интересная идея - делаешь конструктор, создающий объект из потока ввода. И потом просто читаешь файл: при прочтении строки, которая сопоставлена с определенной make-функцией, вызываешь её, а она, в свою очередь, вызывает конструктор с твоим файлом. Ну а вообще, я бы заюзал boost::serialize. В нем, как говорится, All Included. Самое приятное, что boost::serialize не интрузивен, т.е. твои классы вообще не должны ничего на себя брать. Это сообщение отредактировал(а) Chaos A.D. - 27.12.2005, 11:38 --------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest |
|||
|
||||
| Earnest |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 53 Всего: 183 |
Интересная, но не симметричная - куда запись запихать? Приходится делать функцию Save, а тогда уж логичнее Load для симметрии. Правда, ее (Load) можно вызывать и из конструктора, чтобы можно было писать CMyObject Obj(in); - что, действительно, иногда удобно. Добавлено @ 12:54
Лучше (в С++) в базовый поток (istream). -------------------- ... |
||||
|
|||||
| Chaos A.D. |
|
||||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 172 Регистрация: 16.1.2005 Где: 09 RUS Репутация: 6 Всего: 7 |
Мне почему-то вспомнился отрывок из книги Джеффа Элджера C++ For Real Programmers...
Это сообщение отредактировал(а) Chaos A.D. - 27.12.2005, 14:04 --------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest |
||||
|
|||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 53 Всего: 183 |
Не читала...
Но книжка, наверное, хорошая. А вообще, разве ты не чувствуешь, что симметричный код, как-то... более соответствует мировой гармонии? -------------------- ... |
|||
|
||||
| Chaos A.D. |
|
||||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 172 Регистрация: 16.1.2005 Где: 09 RUS Репутация: 6 Всего: 7 |
Хы, оттуда же цитата, которую я полностью поддерживаю:
Вообще, я сам люблю, когда все в проекте гармонично. Например, когда я думаю об одном из своих проектов, который мне приходится сопровождать, у меня в голове мигом рисуется схема того, какая часть программы чего использует, как что-к-чему относится и зависит. И у этого проекта архитектура настолько запутанная, что в голове сплошная мешанина. Поэтому, я ничего не имею против красивого и правильного "симметричного" кода. Просто, цитату смешную вспомнил. --------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest |
||||
|
|||||
| Chaos A.D. |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 172 Регистрация: 16.1.2005 Где: 09 RUS Репутация: 6 Всего: 7 |
А книга есть в электронном формате, но она, как бы вроде для тех, кто только что прочел Страуструпа что-нибудь другое для начинающих. Хотя после Александреску, Саттера и Мейерса перечитывать довольно любопытно. Как-то нестандартно мыслит мужик (хоть и примеры немного надуманные).
--------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest |
|||
|
||||
| GKosh |
|
||||
|
Новичок Профиль Группа: Участник Сообщений: 30 Регистрация: 27.12.2005 Репутация: нет Всего: нет |
Спасибо всем,
boost::serialize гляну, но в моем случае мне нужен очень четкий контроль за создаваемой структурой. Сериализоваться будет дерево, с большим числом полиморфных классов внутри. Соответсвенно должна быть возможность:
и этого должно быть достаточно для каскада динамического выделения памяти под все более удаленные от корня объекты - вообщем, наверное лучше писать самому.
Ну да и строки, и объекты ввиде членов класса и даже вложенные списки - все это учитывается. Что меня больше всего смущает, так это форма в которой я храню указатели на члены класса: struct PROPERTY { const char* sProperty; // имя переменной - члена класса void** pProperty; // указатель на переменную SERIA_TYPE Type; // метка типа переменной (int, float, string, object) }; Вон тот вот void** мне признаться не нравится - можно было бы как-то иначе указывать на член класса (помним, что членом класса может быть указатель на объект другого класса) без void, но чтобы и на int и на string и на условный CMyTree - полагаю использование полиморфной оболочки на int - это будет перебор. |
||||
|
|||||
| DeadSoul |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 1217 Регистрация: 25.9.2005 Где: Москва Репутация: 2 Всего: 11 |
это нужно заменить на varint\ boost::variant \ boost::any. После этого смотри как сериализация устроена в бусте или MFC -------------------- Если Вы получили ответ на Ваш вопрос, то нажмите на "Вопрос решен". Бьем спамеров их же оружием. Пусть весь спам сыпется им [email protected] |
|||
|
||||
| GKosh |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 30 Регистрация: 27.12.2005 Репутация: нет Всего: нет |
Сериализация boost'а мне не годится, нужно, чтобы сэйв можно было бы при необходимости редактировать или даже составлять от руки - нужен парсер команд, навроде color = 100; m_root += CNode и.т.п. Впрочем не суть. boost::any гляну - это как variant в VBasic'е? Или он хранит информация о своем "настоящем" типе? |
|||
|
||||
| Daevaorn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2155 Регистрация: 29.11.2004 Где: Москва Репутация: 51 Всего: 70 |
GKosh
Там голый void*, но использует RTTI для опредеения текущего типа и конвертации в нужный. |
|||
|
||||
| DeadSoul |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 1217 Регистрация: 25.9.2005 Где: Москва Репутация: 2 Всего: 11 |
нет. При изспользование boost::any клиент олжен знать кто там хранится. Тут может пригодится boost::variant(это не тот вариант о котором ты подумал. Это намного круче) -------------------- Если Вы получили ответ на Ваш вопрос, то нажмите на "Вопрос решен". Бьем спамеров их же оружием. Пусть весь спам сыпется им [email protected] |
|||
|
||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |