Boost :: Serialization和MFC Doc / View体系结构 [英] Boost::Serialization and MFC Doc/View architecture

查看:214
本文介绍了Boost :: Serialization和MFC Doc / View体系结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在移植现有的MFC C ++应用程序,以便对XML文件使用Boost :: Serialization。我的CDocument对象包含应用程序的所有数据。我已经实现了serialize函数:

I'm porting an existing MFC C++ application to use Boost::Serialization for XML files. My CDocument object contains all the data for the app. I've implemented the serialize function as:

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:

To capture the save and load events, in the CDoc *.cpp file I have overloaded the base class functions OnOpenDocument() and OnSaveDocument() to implement 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。

Saving a document works fine. The problem is that loading a document doesn't work. The boost library seems to copy the CMyDoc object because the pointer comes back a different address. This means that the loaded file isn't loaded into the current document. Can a CDoc overwrite itself with boost? It can with MFC CArchive.

我想到有一行指示为POSSIBLE解决方案,但这将意味着实现复制构造函数的CMyDoc类。这删除了boost的一个好处,我将有两行代码为每个变量:
1. ar& BOOST_SERIALIZATION_NVP(m_Param1)//用于保存并加载到pDoc
2. this-> m_Param1 = pDoc.m_Param1 //在CMyDoc复制构造函数中

I thought about having the line indicated as "POSSIBLE solution", but this would mean implementing the copy constructor for the CMyDoc class. This removes one of the benefits of boost in that I would have two lines of code for each variable: 1. ar & BOOST_SERIALIZATION_NVP(m_Param1) // for saving and loading to pDoc 2. this->m_Param1 = pDoc.m_Param1 // in CMyDoc copy constructor

CMyView捕获文件打开和保存事件,Doc / View架构提供的MRU列表管理不会发生。

If I overload the CMyView to capture the file open and save events, the MRU list management offered by the Doc/View architecture won't happen.

我确定这已经完成一百万次,但我在网上找不到任何信息。奇怪的!任何帮助非常感激:D

I'm sure this has been done a million times, but I can't find any information online. Weird! Any help much appreciated :D

阅读文档,我看到Boost承认任何序列化的指针反序列化新关键字:指针序列化在库中实现,代码类似于以下内容:

Reading the documentation closer, I see that Boost acknowledges that any serialized pointer is deserialized with a new keyword: "Serialization of pointers is implemented in the library with code similar to the following:"

// 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();
}

文档建议在必要时重载此函数:

The documentation recommends overloading this function if necessary:

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 !!

But this would again result in needed to implement a CMyDoc copy constructor. Aaarrgghhhh!!

如果它帮助任何人,我有一个从罗伯特Ramey的回答这个。基本上,我没有缺少一些明显的:CMyDoc序列化(存档& ar,const无符号int版本)函数不是一个运行,所以我实现单独的boost_save和boost_load函数。我不得不重载OnOpenDocument和OnSaveDocument,例如:

In case it helps anyone, I had a reply from Robert Ramey about this. Basically, I wasn't missing something obvious: the CMyDoc serialize(Archive& ar, const unsigned int version) function wasn't a runner, so I implemented separate boost_save and boost_load functions. I had to overload the OnOpenDocument and OnSaveDocument, for example:

BOOL CMyDoc :: OnOpenDocument(LPCTSTR lpszPathName)
{
clear() / p>

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访问该文件。即使调用Serialize函数中的ar.Abort()也不起作用,因为CDocument基类假设在返回到基类Serialize函数时存在ar。

This is necessary since the MFC CArchive owns the file until the MFC Serialize function exits, disallowing boost::serialization to access the file. Even calling ar.Abort() in the Serialize functions doesn't work because the CDocument base class assumes the ar exists on returning to the base class Serialize function.

推荐答案

有一个非常整洁的解决方案使用Boost.IOStreams:

There's a very neat solution using 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);
}

您不必担心OnOpenDocument / OnSaveDocument。
只是覆盖CDocument :: Serialize并将其转发给Boost.Serialization。

You don't have to bother with OnOpenDocument/OnSaveDocument. Just overwrite the CDocument::Serialize and forward it to Boost.Serialization.

这篇关于Boost :: Serialization和MFC Doc / View体系结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆