| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Visual C++/MFC/WTL > Сериализация |
| Автор: RobinHoodPHD 19.6.2010, 10:22 | ||||||
| Доброго времени суток, Господа! Продолжаю свое мытарство с программой для рисования
Где ObjectList - это экземпляр CObList хранящий мои фигуры. Каждая фигура представлена классом, производным от абстрактного класса Geom, который сам наследует от CObject; Вот такая иерархия: CObject Geom (абстрактный) RCircle, RLine, RRect, ... RDot - это классы моих фигур Для каждого класса фигуры я переопределил функцию Serialize, например для класса класса RCircle:
Класс описан с макросом DECLARE_SERIAL(RCircle) и в реализации есть IMPLEMENT_SERIAL(RCircle, CObject, 1) Сохранять - вроде сохраняет, по крайней мере строка el->Serialize (ar); вызывает функцию Serialize именно для RCircle. Проблема теперь с тем, как это прочитать. Ведь я не знаю какого типа я читаю объект - окружность, линию или чего еще. Кусок кода из CSDI1Doc::Serialize для чтения явно у меня не задался )) и не работает.
Во-первых цикл ни разу не прокручивается => буфер всегда пустой, хотя я вроде сериализовал 3 окружности и сам файл не нулевого размера. В общем вопрос - что я сделал не так, и что мне исправить, чтобы сохранить и восстановить мои объекты. Заранее благодарен за Ваши ответы на мое, немного сумбурное, и путанное изложение проблемы) |
| Автор: Earnest 20.6.2010, 14:01 | ||
Разумеется, перед телом объекта нужно писать его тип. Это можно делать самому или довериться MFC: если для объекта определить макрос DECLARE_SERIAL \ IMPLEMENT_SERIAL, то объект будет сериализоваться сам. Конечно, это не означает, что для абстрактного указателя модно вызвать Serialize, и он каким-то чудом превратится в объект нужного типа (я имею в виду загрузку). Не помню, как это именно происходит в MFC, но схема примерно такая: как я уже говорила, перед телом объекта обязательно записывается его тип - в виде числа или в виде строки, да хоть GUID - на что фантазии хватит. Далее, реализуется фабрика, которая принимает поток (архив) и возвращает объект. Фабрику можно реализовать как отдельный объект, либо как функцию. Если особых наворотов не требуется, то я бы ограничилась статической функцией. Тогда чтение будет выглядеть примерно так:
Ну, switch - это, конечно, если совсем лениво или иерархия объектов простая как тапок и не предполагает развития. Лучше делать объекты само-регистрирующимися. Собственно, DECLARE_SERIAL примерно так и действует. Подробностей не помню, т.к. в свое время мне что-то там не понравилась, и я предпочитаю организовывать фабрики сама. Но суть одна. |
| Автор: RobinHoodPHD 21.6.2010, 20:29 | ||
| Спасибо огромное, Earnest !! Так и сделал - работает как часы. Единственное что не работает- это ar.IsBufferEmpty () - всегда возвращает false, поэтому я просто переделал так:
|
| Автор: Earnest 22.6.2010, 07:12 | ||
Просто эта функция делает не то, что ты полагаешь.
Я обычно проверяю конец чтения просто по факту непрочтения очередной порции байтов: перед чтением каждого объекта ведь нужно прочесть его тип. Получается как-то так: if (ar.Read (&type, sizeof(type) != sizeof(type)) -> приплыли. Ну, и разумеется, try-catch не помешает для аварийных ситуаций (порча файла и т.д.) |