深入浅出MFC第2版(PDF格式)-第110部分
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
// Object I/O is pointer based to avoid added construction overhead。
// Use the Serialize member function directly for embedded objects。
friend CArchive& AFXAPI operator(CArchive& ar; CObject*& pOb);
friend CArchive& AFXAPI operator》》(CArchive& ar; const CObject*& pOb);
// insertion operations
CArchive& operator(unsigned& u);
// object read/write
CObject* ReadObject(const CRuntimeClass* pClass);
void WriteObject(const CObject* pOb);
// advanced object mapping (used for forced references)
void MapObject(const CObject* pOb);
// advanced versioning support
void WriteClass(const CRuntimeClass* pClassRef);
CRuntimeClass* ReadClass(const CRuntimeClass* pClassRefRequested = NULL;
UINT* pSchema = NULL; DWORD* pObTag = NULL);
void SerializeClass(const CRuntimeClass* pClassRef);
。。。
protected:
// array/map for CObject* and CRuntimeClass* load/store
UINT m_nMapCount;
union
{
CPtrArray* m_pLoadArray;
CMapPtrToPtr* m_pStoreMap;
};
// map to keep track of mismatched schemas
CMapPtrToPtr* m_pSchemaMap;
。。。
};
这些多载运算子均定义于AFX。INL 文件中。另有些函数可能你会觉得眼熟,没错,它
们在稍早的「台面下的Serialize 奥秘」中已经出现过了,它们是ReadObject 、WriteObject 、
ReadClass 、WriteClass。
各种类型的operator》》 和operator》(CArchive& ar; const CObject*& pOb)
{ pOb = ar。ReadObject(NULL); return ar; }
其中CArchive::WriteObject 先把类别的CRuntimeClass 信息写出, 再调用类别的
Serialize 函数。CArchive::ReadObject 的行为类似,先把类别的CRuntimeClass 信息读入,
再调用类别的Serialize 函数。Serialize 是CObject 的虚拟函数,因此你必须确定你的
类别改写的Serialize 函数的回返值和参数类型都符合CObject 中的声明:传回值为
void ,唯一一个参数为CArchive&。
注意:CString、CRect、CSize、CPoint 并不衍生自CObject,但它们也可以直接使用针
对CArchive 的》 运算子,因为它们自己设计了一套:
// in AFX。H
class CString
{
friend CArchive& AFXAPI operator(CArchive& ar; CString& string);
。。。
};
// in AFXWIN。H
// Serialization
CArchive& AFXAPI operator(CArchive& ar; RECT& rect);
一个类别如果希望有Serialization 机制,它的第二要件就是使用SERIAL 宏。这个巨
集包容DYNCREATE 宏,并且在类别的声明之中加上:
friend CArchive& AFXAPI operator》》(CArchive& ar; class_name* &pOb);
在类别的实作档中加上:
CArchive& AFXAPI operator》》(CArchive& ar; class_name* &pOb)
{ pOb = (class_name*) ar。ReadObject(RUNTIME_CLASS(class_name));
return ar; }
535
…………………………………………………………Page 598……………………………………………………………
第篇 深入 MFC 程式設計
如果我的类别名为CStroke,那么经由
class CStroke : public CObject
{
。。。
DECLARE_SERIAL(CStroke)
}
和
IMPLEMENT_SERIAL(CStroke; CObject; 1)
我就获得了两组和CArchive 读写动作的关键性程序代码:
class CStroke : CObject
{
。。。
friend CArchive& AFXAPI operator》》(CArchive& ar; CStroke* &pOb);
}
CArchive& AFXAPI operator》》(CArchive& ar; CStroke* &pOb)
{ pOb = (CStroke*) ar。ReadObject(RUNTIME_CLASS(CStroke));
return ar; }
好,你看到了,为什么只改写operator》》 ,而没有改写operator》(CArchive& ar; class_name* &pOb)
{ pOb = (class_name*) ar。ReadObject(RUNTIME_CLASS(class_name));
return ar; }
也就是,令CreateObject 函数为NULL ,这才能够使用于抽象类别之中。
在 CObList 中加入 CStroke 以外的类別
Scribble Document 倾印码中的那个代表「旧类别」的8001 一直令我如坐针毡。不知道
什么情况下会出现8002?或是8003?或是什么其它东东。因此,我打算做点测试。除
了CStroke,我打算再加上CRectangle 和CCircle 两个类别,并把其对象挂到CObList
中。这个修改纯粹为了测试不同类别写到文件档中会造成什么后果,没有考虑使用者介
面或任何外围因素,我并不是真打算为Scribble 加上画四方形和画圆形的功能(不过如
537
…………………………………………………………Page 600……………………………………………………………
第篇 深入 MFC 程式