小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

程序調(diào)試--CObject對象的串行化

 戴維圖書館 2013-01-23

程序調(diào)試--CObject對象的串行化

分類: 深入MFC 168人閱讀 評論(0) 收藏 舉報(bào)

程序代碼

  1. #include <afxwin.h>   
  2. class CMyClass : public CObject  
  3. {  
  4.     DECLARE_SERIAL(CMyClass)  
  5. public:  
  6.     CMyClass(int n = 10) : m_nData(n) {}  
  7.     virtual void Serialize(CArchive& ar);  
  8. protected:  
  9.     int m_nData;  
  10. };  
  11. IMPLEMENT_SERIAL(CMyClass, CObject, 1)  
  12. void CMyClass::Serialize(CArchive& ar)  
  13. {  
  14.     CObject::Serialize(ar);  
  15.     if (ar.IsStoring())  
  16.         ar<<m_nData;  
  17.     else  
  18.         ar>>m_nData;  
  19. }  
  20. int _tmain(int argc, _TCHAR* argv[])  
  21. {  
  22.     CFile file("file.dat", CFile::modeReadWrite | CFile::modeCreate);  
  23.     CArchive ar(&file, CArchive::store);  
  24.       
  25.     CMyClass* pMyClass1 = new CMyClass(2000);  
  26.     ar<<pMyClass1;  
  27.     CMyClass* pMyClass2 = new CMyClass(3000);  
  28.     ar<<pMyClass2;  
  29.     return 0;  
  30. }  
 

 


在序列化宏IMPLEMENT_SERIAL中添加了一個(gè)>>運(yùn)算符的重載,但沒有<<運(yùn)算符的重載。但是在CArchive類中有重載<<的輸出CObject的友元函數(shù),通過它完成了類的串行化。

  1. _AFX_INLINE CArchive& AFXAPI operator<<(CArchive& ar, const CObject* pOb)  
  2.     { ar.WriteObject(pOb); return ar; }  
 

該函數(shù)通過CArchive::WriteObject()將類寫入到文件中。

  1. void CArchive::WriteObject(const CObject* pOb)  
  2. {  
  3.     if (!IsStoring())   
  4.     {  
  5.         AfxThrowArchiveException(CArchiveException::readOnly, m_strFileName);  
  6.     }  
  7.     DWORD nObIndex;  
  8.     // make sure m_pStoreMap is initialized   
  9.     MapObject(NULL);  
  10.     if (pOb == NULL)  
  11.     {  
  12.         // save out null tag to represent NULL pointer   
  13.         *this << wNullTag;  
  14.     }  
  15.     else if ((nObIndex = (DWORD)(DWORD_PTR)(*m_pStoreMap)[(void*)pOb]) != 0)  
  16.     {  
  17.         // 已經(jīng)串行化過的指針,再次串行化只寫入指針?biāo)饕怠?  
  18.         if (nObIndex < wBigObjectTag)  
  19.             *this << (WORD)nObIndex;  
  20.         else  
  21.         {  
  22.             *this << wBigObjectTag;     
  23.             *this << nObIndex;  
  24.         }  
  25.     }  
  26.     else  
  27.     {  
  28.         // 第一次寫入類對象   
  29.         CRuntimeClass* pClassRef = pOb->GetRuntimeClass();  
  30.         WriteClass(pClassRef);      // 寫入類的CRuntimeClass信息   
  31.         CheckCount();       // enter in stored object table, checking for overflow   
  32.         (*m_pStoreMap)[(void*)pOb] = (void*)(DWORD_PTR)m_nMapCount++;   // 映射對象指針   
  33.         // cause the object to serialize itself   
  34.         ((CObject*)pOb)->Serialize(*this);       // 對象自身串行化其內(nèi)部成員變量。   
  35.     }  
  36. }  
 

如果pObj為NULL,則寫入空對象標(biāo)記;如果在CArchive的m_pStoreMap中發(fā)現(xiàn)對象指針的映射,則寫入指針的映射值;如果是第一次寫入,則先寫入類的CRuntimeClass信息,然后調(diào)用類的Serialize()函數(shù)來讓對象自己串行化其成員變量。

CArchive::m_pStoreMap中保存了已寫入對象指針和索引值的映射,寫入的對象指針可以包括支持序列化的類對象指針和CRuntimeClass指針。當(dāng)查到已寫入的指針時(shí),CArchive只是簡單的寫入索引值,后面會(huì)詳細(xì)說明索引值的寫入規(guī)則。


對于第一次寫入對象的情況,首先要通過CArchive::WriteClass()寫入對應(yīng)類的CRuntimeClass結(jié)構(gòu),用于標(biāo)識一個(gè)類。

  1. void CArchive::WriteClass(const CRuntimeClass* pClassRef)  
  2. {  
  3.     if (pClassRef == NULL)   
  4.     {       // 對于void返回值的函數(shù),如果入?yún)⒉粷M足或特定條件不滿足,可拋出異常來處理。   
  5.         AfxThrowArchiveException(CArchiveException::badClass, m_strFileName);  
  6.     }  
  7.     if (!IsStoring())   
  8.     {  
  9.         AfxThrowArchiveException(CArchiveException::genericException, m_strFileName);  
  10.     }  
  11.     if (pClassRef->m_wSchema == 0xFFFF)  
  12.     {  
  13.         TRACE(traceAppMsg, 0, "Warning: Cannot call WriteClass/WriteObject for %hs./n",  
  14.             pClassRef->m_lpszClassName);  
  15.         AfxThrowNotSupportedException();  
  16.     }  
  17.     // make sure m_pStoreMap is initialized   
  18.     MapObject(NULL);  
  19.     // write out class id of pOb, with high bit set to indicate new object follows   
  20.     DWORD nClassIndex;  
  21.     if ((nClassIndex = (DWORD)(DWORD_PTR)(*m_pStoreMap)[(void*)pClassRef]) != 0)  
  22.     {  
  23.         // previously seen class, write out the index tagged by high bit   
  24.         if (nClassIndex < wBigObjectTag)  
  25.             *this << (WORD)(wClassTag | nClassIndex);  
  26.         else  
  27.         {  
  28.             *this << wBigObjectTag;  
  29.             *this << (dwBigClassTag | nClassIndex);  
  30.         }  
  31.     }  
  32.     else  
  33.     {  
  34.         // store new class   
  35.         *this << wNewClassTag;        // 新類標(biāo)記   
  36.         pClassRef->Store(*this); // 寫入版本號、類名稱長度、類名稱字符串   
  37.           
  38.         CheckCount();   // store new class reference in map, checking for overflow   
  39.         (*m_pStoreMap)[(void*)pClassRef] = (void*)(DWORD_PTR)m_nMapCount++;     // 映射對象指針   
  40.     }  
  41. }  
 

函數(shù)中后面的if語句寫入了類的CRuntimeClass信息。如果不是第一次寫入,則寫入對應(yīng)類標(biāo)記。否則,先寫一個(gè)新類標(biāo)記,再寫入版本號、類名稱長度、類名稱字符串,接下來映射結(jié)構(gòu)體指針。

  1. void CRuntimeClass::Store(CArchive& ar) const  
  2. // stores a runtime class description   
  3. {  
  4.     WORD nLen = (WORD)lstrlenA(m_lpszClassName);  
  5.     ar << (WORD)m_wSchema << nLen;  
  6.     ar.Write(m_lpszClassName, nLen*sizeof(char));  
  7. }  
 

 


關(guān)于標(biāo)記。

  1. // Pointer mapping constants   
  2. #define wNullTag        ((WORD)0)           // special tag indicating NULL ptrs   
  3. #define wNewClassTag    ((WORD)0xFFFF)      // special tag indicating new CRuntimeClass   
  4. #define wClassTag       ((WORD)0x8000)      // 0x8000 indicates class tag (OR'd)   
  5. #define dwBigClassTag   ((DWORD)0x80000000) // 0x8000000 indicates big class tag (OR'd)   
  6. #define wBigObjectTag   ((WORD)0x7FFF)      // 0x7FFF indicates DWORD object tag   
  7. #define nMaxMapCount    ((DWORD)0x3FFFFFFE) // 0x3FFFFFFE last valid mapCount  
 

wNullTag是空對象標(biāo)記

wNewClassTag表明一個(gè)新的類的開始

wClassTag通過和類標(biāo)識(在m_pStoreMap中是一個(gè)CRuntimeClass指針的映射)相與,來表明接下來是類的CRuntimeClass信息。

dwBigClassTag和wClassTag作用,唯一區(qū)別在于二者寫入數(shù)據(jù)不同。

wBigObjectTag用來檢測映射值是否應(yīng)該被改寫。

 

nMaxMapCount是m_pStoreMap中最多能存儲(chǔ)的指針映射對數(shù)。

 

寫入的標(biāo)記分兩類:類標(biāo)記和對象標(biāo)記,類標(biāo)表明之前已經(jīng)寫過了類的CRuntimeClass信息,而對象標(biāo)記則表明之前已經(jīng)寫過了一個(gè)相同的對象。類標(biāo)記在最高位是1,這也就是為什么要用wClassTag或dwBigClassTag和指針映射值進(jìn)行或的原因。因?yàn)樽x取的時(shí)候要區(qū)分一個(gè)類是類標(biāo)記或者是對象標(biāo)記,則用wBigObjectTag來區(qū)分,當(dāng)映射值小于wBigObjectTag時(shí),直接寫入映射值;當(dāng)大于或等于映射值時(shí),先寫入wBigObjectTag來表明接下來的4個(gè)字節(jié)是一個(gè)映射值整體。

分享到:

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多