Я портирую существующее приложение MFC C ++ для использования Boost :: Serialization для файлов XML.Мой объект CDocument содержит все данные для приложения.Я реализовал функцию сериализации как:
template<class Archive>
void CMyDoc::serialize(Archive& ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_NVP(m_Param1)
& BOOST_SERIALIZATION_NVP(m_Param2);
}
Чтобы захватить события сохранения и загрузки, в файле CDoc * .cpp я перегрузил функции базового класса OnOpenDocument () и OnSaveDocument () для реализации Boost:: Сериализация:
BOOL CMyDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
clear(); // clear current params
//if (!CDocument::OnOpenDocument(lpszPathName)) // Old MFC serialize code
// return FALSE;
CEvolveTrafficDoc* pDoc = this; // pointers the same here
std::ifstream ifs(lpszPathName);
boost::archive::xml_iarchive ia(ifs);
ia >> boost::serialization::make_nvp("MyDoc",pDoc); // pointer changes here
// *this = *pDoc; // POSSIBLE solution with CMyDoc copy constructor implemented
return TRUE;
}
BOOL CMyDoc::OnSaveDocument(LPCTSTR lpszPathName)
{
//if (!CDocument::OnSaveDocument(lpszPathName)) // Old MFC serialize code
// return FALSE;
std::ofstream ofs(lpszPathName);
boost::archive::xml_oarchive oa(ofs);
oa << boost::serialization::make_nvp("MyDoc",this);
return TRUE;
}
Сохранение документа работает нормально.Проблема в том, что загрузка документа не работает.Кажется, что библиотека boost копирует объект CMyDoc, потому что указатель возвращает другой адрес.Это означает, что загруженный файл не загружен в текущий документ.Может ли CDoc перезаписать себя с помощью boost?Это возможно с MFC CArchive.
Я думал о том, чтобы строка была обозначена как «ВОЗМОЖНОЕ решение», но это означало бы реализацию конструктора копирования для класса CMyDoc.Это устраняет одно из преимуществ boost в том, что у меня будет две строки кода для каждой переменной: 1. ar & BOOST_SERIALIZATION_NVP (m_Param1) // для сохранения и загрузки в pDoc 2. this-> m_Param1 = pDoc.m_Param1 // inКонструктор копирования CMyDoc
Если я перегружу CMyView для захвата событий открытия и сохранения файла, управление списком MRU, предлагаемое архитектурой Doc / View, не произойдет.
Я уверен, что этобыло сделано миллион раз, но я не могу найти какую-либо информацию в Интернете.Weird!Любая помощь приветствуется: D
Читая документацию ближе, я вижу, что Boost признает, что любой сериализованный указатель десериализуется с новым ключевым словом: «Сериализация указателей реализована в библиотеке с кодом, похожим наследующее: "
// load data required for construction and invoke constructor in place
template<class Archive, class T>
inline void load_construct_data(
Archive & ar, T * t, const unsigned int file_version
){
// default just uses the default constructor to initialize
// previously allocated memory.
::new(t)T();
}
В документации рекомендуется перегрузить эту функцию при необходимости:
template<class Archive>
inline void load_construct_data(
Archive & ar, my_class * t, const unsigned int file_version
){
// retrieve data from archive required to construct new instance
int attribute;
ar >> attribute;
// invoke inplace constructor to initialize instance of my_class
::new(t)my_class(attribute);
}
Но это опять-таки приведет к необходимости реализации конструктора копирования CMyDoc.Aaarrgghhhh !!
На случай, если это кому-нибудь поможет, у меня был ответ от Роберта Рами об этом.По сути, я не упустил ничего очевидного: функция CMyDoc serialize (Archive & ar, const unsigned int version) не была раннером, поэтому я реализовал отдельные функции boost_save и boost_load.Мне пришлось перегрузить OnOpenDocument и OnSaveDocument, например:
BOOL CMyDoc :: OnOpenDocument (LPCTSTR lpszPathName) {clear ();
// Call base class function with empty local Serialize function
// to check file exists etc
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
std::string file( lpszPathName );
boost_load(file);
return TRUE;
}
Этонеобходимо, поскольку MFC CArchive владеет файлом до тех пор, пока не завершится функция MFC Serialize, что не разрешает boost :: serialization для доступа к файлу.Даже вызов ar.Abort () в функциях Serialize не работает, потому что базовый класс CDocument предполагает, что ar существует после возврата в функцию Serialize базового класса.