我正在移植现有的 MFC C++ 应用程序以对 XML 文件使用 Boost::Serialization。我的 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::Serialization:
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 // 在 CMyDoc 复制构造函数中
如果我重载 CMyView 来捕获文件打开和保存事件,则 Doc/View 架构提供的 MRU 列表管理将不会发生。
我确信这已经被执行了一百万次,但我在网上找不到任何信息。诡异的!非常感谢任何帮助: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 复制构造函数。啊啊啊啊!!
如果它对任何人有帮助,我收到了罗伯特·雷米(Robert Ramey)对此的回复。基本上,我没有遗漏一些明显的东西:CMyDoc serialize(Archive& ar, const unsigned int version) 函数不是运行程序,因此我实现了单独的 boost_save 和 boost_load 函数。我必须重载 OnOpenDocument 和 OnSaveDocument,例如:
BOOL CMyDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
清除();
// 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 访问该文件。即使在 Serialize 函数中调用 ar.Abort() 也不起作用,因为 CDocument 基类假定 ar 在返回到基类 Serialize 函数时存在。