程序代码
在序列化宏IMPLEMENT_SERIAL中添加了一个>>运算符的重载,但没有<<运算符的重载。但是在CArchive类中有重载<<的输出CObject的友元函数,通过它完成了类的串行化。
该函数通过CArchive::WriteObject()将类写入到文件中。
如果pObj为NULL,则写入空对象标记;如果在CArchive的m_pStoreMap中发现对象指针的映射,则写入指针的映射值;如果是第一次写入,则先写入类的CRuntimeClass信息,然后调用类的Serialize()函数来让对象自己串行化其成员变量。
CArchive::m_pStoreMap中保存了已写入对象指针和索引值的映射,写入的对象指针可以包括支持序列化的类对象指针和CRuntimeClass指针。当查到已写入的指针时,CArchive只是简单的写入索引值,后面会详细说明索引值的写入规则。
对于第一次写入对象的情况,首先要通过CArchive::WriteClass()写入对应类的CRuntimeClass结构,用于标识一个类。
函数中后面的if语句写入了类的CRuntimeClass信息。如果不是第一次写入,则写入对应类标记。否则,先写一个新类标记,再写入版本号、类名称长度、类名称字符串,接下来映射结构体指针。
关于标记。
wNullTag是空对象标记
wNewClassTag表明一个新的类的开始
wClassTag通过和类标识(在m_pStoreMap中是一个CRuntimeClass指针的映射)相与,来表明接下来是类的CRuntimeClass信息。
dwBigClassTag和wClassTag作用,唯一区别在于二者写入数据不同。
wBigObjectTag用来检测映射值是否应该被改写。
nMaxMapCount是m_pStoreMap中最多能存储的指针映射对数。
写入的标记分两类:类标记和对象标记,类标表明之前已经写过了类的CRuntimeClass信息,而对象标记则表明之前已经写过了一个相同的对象。类标记在最高位是1,这也就是为什么要用wClassTag或dwBigClassTag和指针映射值进行或的原因。因为读取的时候要区分一个类是类标记或者是对象标记,则用wBigObjectTag来区分,当映射值小于wBigObjectTag时,直接写入映射值;当大于或等于映射值时,先写入wBigObjectTag来表明接下来的4个字节是一个映射值整体。