首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >结构数据中CArchive算子过载的条件读取

结构数据中CArchive算子过载的条件读取
EN

Stack Overflow用户
提问于 2022-10-22 09:16:48
回答 1查看 71关注 0票数 0

我有两个序列化操作符重载:

代码语言:javascript
复制
friend CArchive& operator<<(CArchive& rArchive, S_MEMORIAL_INFO const& rsMI)
{
    return rArchive << rsMI.strHost
        << rsMI.strCohost
        << rsMI.strZoomAttendant
        << rsMI.strChairman
        << rsMI.strPrayerOpen
        << rsMI.strPrayerClose
        << rsMI.strSpeaker
        << rsMI.strImagePath
        << rsMI.strTextBeforeImage
        << rsMI.strTextAfterImage
        << rsMI.iImageWidthAsPercent
        << rsMI.iSongOpen
        << rsMI.iSongClose;

}

friend CArchive& operator>>(CArchive& rArchive, S_MEMORIAL_INFO& rsMI)
{
    return rArchive >> rsMI.strHost
        >> rsMI.strCohost
        >> rsMI.strZoomAttendant
        >> rsMI.strChairman
        >> rsMI.strPrayerOpen
        >> rsMI.strPrayerClose
        >> rsMI.strSpeaker
        >> rsMI.strImagePath
        >> rsMI.strTextBeforeImage
        >> rsMI.strTextAfterImage
        >> rsMI.iImageWidthAsPercent
        >> rsMI.iSongOpen
        >> rsMI.iSongClose;
}

但是我现在想引入版本跟踪,这样我就可以在不给用户造成软件崩溃的情况下处理新的字段。

所以现在我想:

代码语言:javascript
复制
friend CArchive& operator>>(CArchive& rArchive, S_MEMORIAL_INFO const& rsMI)
{
    WORD wVersion{};

    rArchive >> wVersion
        >> rsMI.strHost
        >> rsMI.strCohost
        >> rsMI.strZoomAttendant
        >> rsMI.strChairman
        >> rsMI.strPrayerOpen
        >> rsMI.strPrayerClose
        >> rsMI.strSpeaker;

    rsMI.strTheme.Empty();
    if(wVersion >= 2)
        rArchive >> rsMI.strTheme;

    return rArchive >> rsMI.strImagePath
        >> rsMI.strTextBeforeImage
        >> rsMI.strTextAfterImage
        >> rsMI.iImageWidthAsPercent
        >> rsMI.iSongOpen
        >> rsMI.iSongClose;

}

friend CArchive& operator<<(CArchive& rArchive, S_MEMORIAL_INFO& rsMI)
{
    WORD wVersion = 2;
    return rArchive << wVersion
        << rsMI.strHost
        << rsMI.strCohost
        << rsMI.strZoomAttendant
        << rsMI.strChairman
        << rsMI.strPrayerOpen
        << rsMI.strPrayerClose
        << rsMI.strSpeaker
        << rsMI.strTheme
        << rsMI.strImagePath
        << rsMI.strTextBeforeImage
        << rsMI.strTextAfterImage
        << rsMI.iImageWidthAsPercent
        << rsMI.iSongOpen
        << rsMI.iSongClose;
}

现在我该如何应对这样一个事实:对于某些用户来说,存档中没有WORD值?

事后看来,我会设计序列化,从一开始就写一个版本号,但现在太迟了。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-10-22 16:09:49

正如注释中所指出的,问题是当从归档中读取wVersion时,这会从下面的CString对象中删除两个字节。CArchive执行自己的缓冲区管理。类定义包含多个成员变量,很容易找到它们在做什么。但是,这些成员是受保护的,因此我们需要定义一个派生类,其中包含一个成员,该成员将当前的缓冲区指针设置为两个字节:

代码语言:javascript
复制
class CArchiveHlp : public CArchive
{
    public :
    void GoBack2()
    {
        if (m_lpBufCur - m_lpBufStart < 2)
            AfxThrowFileException(CFileException::genericException);
        m_lpBufCur -= 2;
    }
};

然后,您可以在代码中使用这个类,如下所示:

代码语言:javascript
复制
    rArchive >> wVersion;
    if (wVersion != 2) // Or any other valid version number
    {
        ((CArchiveHlp*)&rArchive)->GoBack2();
        wVersion = 0;
    }
    rArchive >> rsMI.strHost
    .
    .

(CArchiveHlp*)强制转换在某种程度上是错误的,因为实际对象不是CArchiveHlp ( dynamic_cast在这里会失败),但是类几乎是相同的,而且GoBack2()成员不是虚拟的(所以没有v表),因此您可以毫无问题地调用它--它调用CArchive类实例的CArchiveHlp代码,其内存中的数据是相同的。

这是经过测试和工作的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74162340

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档