我有两个序列化操作符重载:
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;
}但是我现在想引入版本跟踪,这样我就可以在不给用户造成软件崩溃的情况下处理新的字段。
所以现在我想:
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值?
事后看来,我会设计序列化,从一开始就写一个版本号,但现在太迟了。
发布于 2022-10-22 16:09:49
正如注释中所指出的,问题是当从归档中读取wVersion时,这会从下面的CString对象中删除两个字节。CArchive执行自己的缓冲区管理。类定义包含多个成员变量,很容易找到它们在做什么。但是,这些成员是受保护的,因此我们需要定义一个派生类,其中包含一个成员,该成员将当前的缓冲区指针设置为两个字节:
class CArchiveHlp : public CArchive
{
public :
void GoBack2()
{
if (m_lpBufCur - m_lpBufStart < 2)
AfxThrowFileException(CFileException::genericException);
m_lpBufCur -= 2;
}
};然后,您可以在代码中使用这个类,如下所示:
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代码,其内存中的数据是相同的。
这是经过测试和工作的。
https://stackoverflow.com/questions/74162340
复制相似问题