C++ Boost::序列化和MFC文档/视图体系结构
我正在移植一个现有的MFC C++应用程序,使用XML文件的Boo::序列化。My CDocument对象包含应用程序的所有数据。我已将序列化函数实现为:C++ Boost::序列化和MFC文档/视图体系结构,c++,mfc,boost-serialization,C++,Mfc,Boost Serialization,我正在移植一个现有的MFC C++应用程序,使用XML文件的Boo::序列化。My CDocument对象包含应用程序的所有数据。我已将序列化函数实现为: template<class Archive> void CMyDoc::serialize(Archive& ar, const unsigned int version) { ar & BOOST_SERIALIZATION_NVP(m_Param1) & BOOST_SERIALIZATIO
template<class Archive>
void CMyDoc::serialize(Archive& ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_NVP(m_Param1)
& BOOST_SERIALIZATION_NVP(m_Param2);
}
}
这是必要的,因为在MFC Serialize函数退出之前,MFC CArchive拥有该文件,因此不允许boost::serialization访问该文件。即使在Serialize函数中调用ar.Abort()也不起作用,因为CDocument基类假设在返回基类Serialize函数时ar存在。重新阅读上面的内容,我发现这不是一个完整的答案。希望这更有帮助 首先(我遗憾地发现了这一点),将第一个参数设为
CMyDoc
版本号变量。我有一个受保护的成员:unsigned int m_版本代码>然后类构造函数是:
CMyDoc::CMyDoc(): m_Version(1) // The current file structure version
{
// construction code
}
这使您可以轻松地读取以前的文件版本。以下是四个函数,分别用于加载和保存
装载:
BOOL CMyDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
clear(); // avoid memory leaks if necessary
// Call base class function with empty local Serialize function
// to check file etc
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
std::string file( lpszPathName );
try {
boost_load(file);
}
catch (const boost::archive::archive_exception& ae)
{
CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd);
CView * pView = pFrame->GetActiveView();
ostringstream str;
str << "Problem loading file.\n"
<< "Boost reports: " << ae.what() << '\n'
<< "Possibly: " << extraArchiveWhat(ae.what())
<< std::ends;
MessageBox(pView->GetSafeHwnd(),str.str().c_str(), "MyApp", MB_OK|MB_ICONERROR);
return FALSE;
}
// If we get here we have been successful
return TRUE;
}
int CSimbaDoc::boost_load(std::string file)
{
std::ifstream ifs(file);
boost::archive::xml_iarchive ia(ifs);
int file_version; // local so as not to write over class m_Version
ia >> boost::serialization::make_nvp("m_Version", file_version)
>> BOOST_SERIALIZATION_NVP(m_Param1)
>> BOOST_SERIALIZATION_NVP(m_Param2);
if(file_version > 0) // read a variable added to class after version 0
ia >> BOOST_SERIALIZATION_NVP(m_Param3);
// and anything else you need to read
}
boolcmydoc::OnOpenDocument(LPCTSTR lpszPathName)
{
clear();//必要时避免内存泄漏
//使用空的本地序列化函数调用基类函数
//检查文件等
如果(!CDocument::OnOpenDocument(lpszPathName))
返回FALSE;
std::字符串文件(lpszPathName);
试一试{
boost_加载(文件);
}
捕获(const boost::archive::archive\u异常和ae)
{
CFrameWnd*pFrame=(CFrameWnd*)(AfxGetApp()->m_pMainWnd);
CView*pView=pFrame->GetActiveView();
ostringstream str;
str BOOST_SERIALIZATION_NVP(m_Param2);
if(file_version>0)//读取在版本0之后添加到类中的变量
ia>>BOOST_序列化_NVP(m_参数3);
//还有什么你需要读的吗
}
为了节省开支:
BOOL CMyDoc::OnSaveDocument(LPCTSTR lpszPathName)
{
// Call base class function with empty local Serialize function
// to check file etc
if (!CDocument::OnSaveDocument(lpszPathName))
return FALSE;
std::string file( lpszPathName );
boost_save(file);
return TRUE;
}
int CSimbaDoc::boost_save(std::string file)
{
std::ofstream ofs(file);
boost::archive::xml_oarchive oa(ofs);
oa << BOOST_SERIALIZATION_NVP(m_Version) // always save current class version
<< BOOST_SERIALIZATION_NVP(m_Param1)
<< BOOST_SERIALIZATION_NVP(m_Param2)
<< BOOST_SERIALIZATION_NVP(m_Param3);
// and whatever else
}
boolcmydoc::OnSaveDocument(LPCTSTR lpszPathName)
{
//使用空的本地序列化函数调用基类函数
//检查文件等
如果(!CDocument::OnSaveDocument(lpszPathName))
返回FALSE;
std::字符串文件(lpszPathName);
boost_保存(文件);
返回TRUE;
}
int CSimbaDoc::boost_save(std::string文件)
{
std::ofs流(文件);
boost::archive::xml_oarchive oa(ofs);
oa使用Boost.IOStreams有一个非常简洁的解决方案:
// We mean to not track this class, or you'll get object-tracking warnings
BOOST_CLASS_TRACKING(MyDoc, boost::serialization::track_never)
void MyDoc::Serialize(CArchive& ar)
{
namespace io = boost::iostreams;
io::file_descriptor fd(ar.GetFile()->m_hFile, io::never_close_handle);
io::stream<io::file_descriptor> file(fd);
if (ar.IsStoring())
{
boost::archive::xml_oarchive oa(file);
oa << *this;
}
else
{
boost::archive::xml_iarchive ia(file);
ia >> *this;
// then update the views...
}
}
template<class Archive>
void MyDoc::serialize(Archive & ar, unsigned version)
{
// Your Boost.Serialization code here
ar & BOOST_SERIALIZATION_NVP(member);
}
//我们的意思是不跟踪此类,否则您将收到对象跟踪警告
BOOST\u类跟踪(MyDoc,BOOST::serialization::track\u never)
void MyDoc::序列化(CArchive&ar)
{
名称空间io=boost::iostreams;
io::file_描述符fd(ar.GetFile()->m_hFile,io::never_close_handle);
io::流文件(fd);
if(ar.IsStoring())
{
boost::archive::xml\u oarchive oa(文件);
oa>*这个;
//然后更新视图。。。
}
}
模板
void MyDoc::序列化(存档&ar,未签名版本)
{
//这里是你的Boost.Serialization代码
ar&BOOST\U序列化\U NVP(成员);
}
您不必为OnPendDocument/OnSaveDocument操心。
只需覆盖CDocument::Serialize并将其转发到Boost.Serialization即可。我一直认为这是一个非常优雅的解决方案。我只是想说声谢谢(尽管已经有一段时间了!)节点-值对是必需的:顺便说一句-boost::iostreams有什么魔力使std::iostreams不起作用?我两个都试过了,但正如您所指出的,只有boost起作用。@Colin您可能感兴趣。
CMyDoc::CMyDoc(): m_Version(1) // The current file structure version
{
// construction code
}
BOOL CMyDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
clear(); // avoid memory leaks if necessary
// Call base class function with empty local Serialize function
// to check file etc
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
std::string file( lpszPathName );
try {
boost_load(file);
}
catch (const boost::archive::archive_exception& ae)
{
CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd);
CView * pView = pFrame->GetActiveView();
ostringstream str;
str << "Problem loading file.\n"
<< "Boost reports: " << ae.what() << '\n'
<< "Possibly: " << extraArchiveWhat(ae.what())
<< std::ends;
MessageBox(pView->GetSafeHwnd(),str.str().c_str(), "MyApp", MB_OK|MB_ICONERROR);
return FALSE;
}
// If we get here we have been successful
return TRUE;
}
int CSimbaDoc::boost_load(std::string file)
{
std::ifstream ifs(file);
boost::archive::xml_iarchive ia(ifs);
int file_version; // local so as not to write over class m_Version
ia >> boost::serialization::make_nvp("m_Version", file_version)
>> BOOST_SERIALIZATION_NVP(m_Param1)
>> BOOST_SERIALIZATION_NVP(m_Param2);
if(file_version > 0) // read a variable added to class after version 0
ia >> BOOST_SERIALIZATION_NVP(m_Param3);
// and anything else you need to read
}
BOOL CMyDoc::OnSaveDocument(LPCTSTR lpszPathName)
{
// Call base class function with empty local Serialize function
// to check file etc
if (!CDocument::OnSaveDocument(lpszPathName))
return FALSE;
std::string file( lpszPathName );
boost_save(file);
return TRUE;
}
int CSimbaDoc::boost_save(std::string file)
{
std::ofstream ofs(file);
boost::archive::xml_oarchive oa(ofs);
oa << BOOST_SERIALIZATION_NVP(m_Version) // always save current class version
<< BOOST_SERIALIZATION_NVP(m_Param1)
<< BOOST_SERIALIZATION_NVP(m_Param2)
<< BOOST_SERIALIZATION_NVP(m_Param3);
// and whatever else
}
// We mean to not track this class, or you'll get object-tracking warnings
BOOST_CLASS_TRACKING(MyDoc, boost::serialization::track_never)
void MyDoc::Serialize(CArchive& ar)
{
namespace io = boost::iostreams;
io::file_descriptor fd(ar.GetFile()->m_hFile, io::never_close_handle);
io::stream<io::file_descriptor> file(fd);
if (ar.IsStoring())
{
boost::archive::xml_oarchive oa(file);
oa << *this;
}
else
{
boost::archive::xml_iarchive ia(file);
ia >> *this;
// then update the views...
}
}
template<class Archive>
void MyDoc::serialize(Archive & ar, unsigned version)
{
// Your Boost.Serialization code here
ar & BOOST_SERIALIZATION_NVP(member);
}