八宝书库 > 文学其他电子书 > 深入浅出MFC第2版(PDF格式) >

第109部分

深入浅出MFC第2版(PDF格式)-第109部分

小说: 深入浅出MFC第2版(PDF格式) 字数: 每页4000字

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




                             { 

                                     WORD w; 

                                     ar 》》 w; 

                                     m_nPenWidth = w; 

                                     m_pointArray。Serialize(ar); 

                             } 

                     } 



528 


…………………………………………………………Page 591……………………………………………………………

                                                        第8章    Document…View  深入探討 



CObject 类别 



     为什么绝大部份的MFC 类别,以及许多你自己的类别,都要从CObject 衍生下来呢? 



     因为当一个类别衍生自CObject,它也就继承了许多重要的性质。CObject 这个「老祖 



     宗」至少提供两个机能(两个虚拟函数):IsKindOf 和IsSerializable 。 



 IsKindOf 



     当Framework 掌握「类别型录网」这张王牌,要设计出IsKindOf 根本不是问题。所谓 



     IsKindOf 就是RTTI  的化身,用白话说就是「xxx 对象是一种xxx 类别吗?」例如「长 



     臂猿是一种哺乳类吗?」「蓝鲸是一种鱼类吗?」凡支持RTTI  的程序就必须接受这类 



     询问,并对前者回答Yes ,对后者回答No 。 



     下面是CObject::IsKindOf 虚拟函数的源代码: 



      // in OBJCORE。CPP 

      BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const 

      { 

              // simple SI case 

              CRuntimeClass* pClassThis = GetRuntimeClass(); 

              return pClassThis…》IsDerivedFrom(pClass); 

      } 



      BOOL CRuntimeClass::IsDerivedFrom(const CRuntimeClass* pBaseClass) const 

      { 

              // simple SI case 

              const CRuntimeClass* pClassThis = this; 

              while (pClassThis != NULL) 

              { 

                      if (pClassThis == pBaseClass) 

                              return TRUE; 

                      pClassThis = pClassThis…》m_pBaseClass; 

              } 

              return FALSE;       // walked to the top; no match 

      } 



     这项作为,也就是在图8…9 中借着m_pBaseClass 寻根。只要在寻根过程中比对成功, 



     就传回TRUE , 否则传回FALSE  。而你知道, 图8…9 的「类别型录网」是靠 



     DECLARE_DYNAMIC 和IMPLEMENT_DYNAMIC 宏构造起来的。第3 章的 



                                                                                         529 


…………………………………………………………Page 592……………………………………………………………

                      第篇    深入  MFC  程式設計 



                      「RTTI 」一节对此多有说明。 



                IsSerializable 



                     一个类别若要能够进行Serialization 动作,必须准备Serialize  函数,并且在「类别型录 



                     网」中自己的那个CRuntimeClass 元素里的schema 字段里设立0xFFFF  以外的号码, 



                     代表资料格式的版本(这样才能提供机会让设计较佳的Serialize  函数能够区分旧版资料 



                     或新版资料, 避免牛头不对马嘴的困惑) 。这些都是DECLARE_SERIAL 和 



                     IMPLEMENT_SERIAL 宏的责任范围。 



                           CObject::classCObject     CCmdTarget::classCCmdTarget      CWinThread::classCWinThread 



                                 “CObject”                    “CCmdTarget”                   “CWinThread” 



                            m_pfnCreateObject   NULL        m_pfnCreateObject  NULL        m_pfnCreateObject  NULL 

                              m_pBaseClass                   m_pBaseClass                    m_pBaseClass 

                              m_pNextClass                    m_pNextClass                   m_pNextClass 



                                              NULL 

                       NULL 



                         CFrameWnd::classCFrameWnd         CWnd::classCWnd              CWinApp::classCWinApp 



                               “CFrameWnd”                      “CWnd”                        “CWinApp” 



                            m_pfnCreateObject               m_pfnCreateObject              m_pfnCreateObject  NULL 

                              m_pBaseClass                   m_pBaseClass                    m_pBaseClass 

                              m_pNextClass                    m_pNextClass                   m_pNextClass 



                           CDocument::classCDocument       CView::classCView 



                               “CDocument”                      “CView” 



                            m_pfnCreateObject               m_pfnCreateObject 

                                                NULL                           NULL 

                              m_pBaseClass                   m_pBaseClass 

                              m_pNextClass                    m_pNextClass 



                                                                                               CRuntimeClass::pFirstClass 



                                   图8…9 DECLARE_ 和IMPLEMENT_ 宏合力构造起这张网。于是RTTI 



                                      和Dynamic Creation 和Serialization 等机能便可轻易达成。 



530 


…………………………………………………………Page 593……………………………………………………………

                                                   第8章    Document…View  深入探討 



      CObject 提供了一个虚拟函数,让程序在执行时期判断某类别的schema 号码是否为 



      0xFFFF,藉此得知它是否可以Serialize: 



         BOOL CObject::IsSerializable() const 



         { 



          return (GetRuntimeClass()…》m_wSchema != 0xffff); 



         } 



CObject::Serialize 



      这是一个虚拟函数。每一个希望具备Serialization 能力的类别都应该改写它。事实上 



      Wizard 为我们做出来的程序代码中也都会自动加上这个函数的调用动作。MFC 手册上总 



      是说,每一个你所改写的Serialize  函数都应该在第一时间调用此一函数,那么是不是 



      CObject::Serialize 之中有什么重要的动作? 



      // in AFX。INL 



      _AFX_INLINE void CObject::Serialize(CArchive&) 



          { /* CObject does not serialize anything by default */ } 



      不,什么也没有。所以,现阶段(至少截至MFC 4。0 )你可以不必理会手册上的谆谆告 



      诲。然而,Microsoft 很有可能改变CObject::Serialize  的内容,届时没有遵循告诲的人 



      恐怕就后悔了。 



CArchive 类别 



      谈到Serialize 就不能不谈CArchive,因为serialize 的对象(无论读或写)是一个 



      CArchive 对象,这一点相信你已经从上面数节讨论中熟悉了。基本上你可以想象archive 



      相当于文件,不过它其实是文件之前的一个内存缓冲区。所以我们才会在前面的「台 



      面下的Serialize 奥秘」中看到这样的动作: 



      BOOL CDocument::OnSaveDocument(LPCTSTR lpszPathName) 



      { 



           CFile* pFile = NULL; 



           pFile = GetFile(lpszPathName; CFile::modeCreate | 



                 CFile::modeReadWrite | CFile::shareExclusive; &fe); 



           // 令file 和archive 产生关联 



                                                                                 531 


…………………………………………………………Page 594……………………………………………………………

                   第篇    深入  MFC  程式設計 



                       CArchive saveArchive(pFile; CArchive::store | 

                                                CArchive::bNoFlushOnDelete); 

                       。。。 

                       Serialize(saveArchive);    //对着 archive 做serialize 动作 

                       。。。 

                       saveArchive。Close(); 

                       ReleaseFile(pFile; FALSE); 

                    } 



                   BOOL CDocument::OnOpenDocument(LPCTSTR lpszPathName) 

                    { 

                       CFile* pFile = GetFile(lpszPathName; 

                                                  CFile::modeRead|CFile::shareDenyWrite; &fe); 



                       // 令file 和archive 产生关联 

                       CArchive loadArchive(pFile; CArchive::load | 

                                              CArchive::bNoFlushOnDelete); 

                       。。。 

                       Serialize(loadArchive);    // 对着archive 做serialize 动作 

                       。。。 

                       loadArchive。Close(); 

                       ReleaseFile(pFile; FALSE); 

                    } 



             operator》 



                   CArchive 针对许多C++ 数据类型、Windows 数据类型以及CObject 衍生类别,定义 



                   operator》 多载运算子: 



                    // in AFX。H 

                    class CArchive 

                    { 

                   public: 

                    // Flag values 

                           enum Mode { store = 0; load = 1; bNoFlushOnDelete = 2; bNoByteSwap = 4 }; 

                           CArchive(CFile* pFile; UINT nMode; int nBufSize = 4096; void* lpBuf = NULL); 

                           ~CArchive(); 



                    // Attributes 

                           BOOL IsLoading() const; 

                           BOOL IsStoring() const; 

                           BOOL IsByteSwapping() const; 

                           BOOL IsBufferEmpty() const; 



                           CFile* GetFile() const; 



532 


…………………………………………………………Page 595……………………………………………………………

                                                  第8章    Document…View  深入探討 



        UINT GetObjectSchema(); // only valid when reading a CObject* 

        void SetObjectSchema(UINT nSchema); 



        // pointer to document being serialized …must set to serialize 

        //  COleClientItems in a document! 

        CDocument* m_pDocument; 



// Operations 

        UINT Read(void* lpBuf; UINT nMax); 

        void Write(const void* lpBuf; UINT nMax); 

        void Flush(); 

        void Close(); 

        void Abort();   // close and shutdown without exceptions 



        // reading and writing strings 

        void WriteString(LPCTSTR lpsz); 

        LPTSTR ReadString(LPTSTR lpsz; UINT nMax); 

        BOOL ReadString(CString& rString); 



public: 

        // Object I/O is pointer based to avoid added construction overhead。 

        // Use the Serialize

返回目录 上一页 下一页 回到顶部 0 0

你可能喜欢的