青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

cc

  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
  38 隨筆 :: 14 文章 :: 21 評論 :: 0 Trackbacks

                     ////////////////////////////////////////////////////////////////////////////////////
                     /********* 文章系列:MFC技術內幕系列***********/
                     /************MFC技術內幕系列之(三)***********/
                     /*文章題目:MFC執行期類型識別與動態創建技術內幕*/
                     /*                   Copyright(c)2002 bigwhite                    */
                     /*                          All rights Reserved                         */
                     /*******關鍵字:執行期類型識別,動態創建*******/
                     /*                          時間:2002.7.23                            */
                     /*    注釋:本文所涉及的程序源代碼均在Microsoft    */
                     /          Visual Studio.Net Enterprise Architect Edition      /
                     /*                  開發工具包提供的源代碼中                  */
                    
////////////////////////////////////////////////////////////////////////////////////////////////
引言:
    眾所周知,微軟的MFC Application Framework建立在一系列先進的程序設計技術上的。比如:消息映射機制,命令傳遞機制,執行期類型識別與動態創建技術及文檔序列化技術等。其中執行期類型識別與動態創建技術是其中最重要的技術之一。微軟在MFC中用一些神秘的宏實現了這種機制,但是對于學習MFC程序設計的初學者來說它卻成為了一大難點,所以在這篇文章中我將詳細地為大家挖掘其中的內幕。

正文:
    MFC執行期類型識別與動態創建技術是借助CRuntimeClass結構和一系列神秘的宏實現的。而動態創建技術 的前提是執行期類型識別網的建立。下面就讓我們來看看執行期類型識別網是如何建立起來的?
                       ///////////////////////////////////////////////////
                       /*一. 1.CRuntimeClass結構總覽 */
                       ///////////////////////////////////////////////////
   注釋:CRuntimeClass結構定義在..\Visual Studio.NET\vc7\atlmfc\include\Afx.h中
// object type information  
struct CRuntimeClass
{
// Attributes
 LPCSTR m_lpszClassName;
 int m_nObjectSize;
 UINT m_wSchema; // schema number of the loaded class
 CObject* (PASCAL* m_pfnCreateObject)(); // NULL => abstract class
#ifdef _AFXDLL
 CRuntimeClass* (PASCAL* m_pfnGetBaseClass)();
#else
 CRuntimeClass* m_pBaseClass;
#endif
// Operations
 CObject* CreateObject();
 BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const;

 // dynamic name lookup and creation
 static CRuntimeClass* PASCAL FromName(LPCSTR lpszClassName);//for ANSI
 static CRuntimeClass* PASCAL FromName(LPCWSTR lpszClassName);//for Unicode
 static CObject* PASCAL CreateObject(LPCSTR lpszClassName);  for ANSI
 static CObject* PASCAL CreateObject(LPCWSTR lpszClassName);//for Unicode
// Implementation
 void Store(CArchive& ar) const;
 static CRuntimeClass* PASCAL Load(CArchive& ar, UINT* pwSchemaNum);
       
       // CRuntimeClass objects linked together in simple list
 CRuntimeClass* m_pNextClass;       // linked list of registered classes
 const AFX_CLASSINIT* m_pClassInit;
};

                       /////////////////////////////////////////////////////////
                       /* 一.2.執行期類型識別網組成部分 */
                       //////////////////////////////////////////////////////////
  在CRuntimeClass結構中與執行期類型識別網建立有關的成員如下:
  struct CRuntimeClass
  { 
      ...//
      LPCSTR m_lpszClassName;
      CRuntimeClass* m_pBaseClass;
            
   }

 
                       //////////////////////////////////////////////////////////
                       /*一.3.執行期類型識別網的連接建立*/
                       //////////////////////////////////////////////////////////
   MFC在每一個具有執行期類型識別能力的類的.h和.cpp文件中都添加了兩個宏。他們是:
//in xx.h
  class class_name
  {
      DECLARE_DYNAMIC(class_name)
      ...//
  }
//in xx.cpp
  IMPLEMENT_DYNAMIC(class_name, base_class_name)
  ...//
  這兩個宏展開后是什么樣子呢?讓我們看看其源代碼吧!
  注釋:這兩個宏定義在..\Visual Studio.NET\vc7\atlmfc\include\Afx.h中
 
  #define DECLARE_DYNAMIC(class_name) \
  public: \
 static const CRuntimeClass class##class_name; \
 virtual CRuntimeClass* GetRuntimeClass() const; \


  #define IMPLEMENT_DYNAMIC(class_name, base_class_name) \
 IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL, NULL)

 
  #define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew, class_init) \
  AFX_COMDAT const CRuntimeClass class_name::class##class_name = { \
  #class_name, sizeof(class class_name), wSchema, pfnNew, \
   RUNTIME_CLASS(base_class_name), NULL, class_init }; \
  CRuntimeClass* class_name::GetRuntimeClass() const \
  { return RUNTIME_CLASS(class_name); } \
  相關宏定義如下:
  #define RUNTIME_CLASS(class_name) _RUNTIME_CLASS(class_name)
  #define _RUNTIME_CLASS(class_name) ((CRuntimeClass*)(&class_name::class##class_name))
 
  看清了吧!這兩個宏互相配合著在每個類中都塞進了點東東,至于什么東東,自己看唄兒!
 
  下面我以一個具體的類來展示以下執行期類型識別網是如何連接建立的。
  以一個MDI應用程序的CMainFrame類為例:
  //in MaimFrm.h
  class CMainFrame : public CMDIFrameWnd
 {
 DECLARE_DYNAMIC(CMainFrame)
         ...//
 }

  //in MaimFrm.cpp
  IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd)
  ...//

  展開后得:
  //in MaimFrm.h
  class CMainFrame : public CMDIFrameWnd
 {
  public:
 static const CRuntimeClass classCMainFrame;
 virtual CRuntimeClass* GetRuntimeClass() const;
    ...//
 }

  //in MaimFrm.cpp
 
  AFX_COMDAT const CRuntimeClass CMainFrame::classCMainFrame ={CMainFrame,sizeof(classCMainFrame  ),0xFFFF,NULL,(CRuntimeClass*)(&CMDIFrameWnd::classCMDIFrameWnd),NULL,NULL};

  CRuntimeClass* CMainFrame::GetRuntimeClass() const
  { return &CMainFrame::classCMainFrame; }
  有上面的代碼可以看到IMPLEMENT_DYNAMIC宏初始化和實現了DECLARE_DYNAMIC宏為CMainFrame添加的CRuntimeClass classCMainFrame和CRuntimeClass* GetRuntimeClass() const靜態函數。
其中最重要的一點是:   CMainFrame類的classCMainFrame對象的CRuntimeClass* m_pBaseClass被“間接的”賦值為&CMDIFrameWnd::classCMDIFrameWnd,也就是它基類的靜態CRuntimeClass classCMDIFrameWnd成員。
以此類推一:
   CMDIFrameWnd::classCMDIFrameWnd的成員CRuntimeClass* m_pBaseClass被“間接的”賦值為
其基類&CFrameWnd::classCFrameWnd;
   ....
   ....
   CCmdTarget::classCCmdTarget的成員CRuntimeClass* m_pBaseClass被“間接的”賦值為&CObject::classCObject;
   CObject沒有基類,那么CObject::classCObject的成員CRuntimeClass* m_pBaseClass被賦予什么值呢?看看what is the special runtime-class structure for CObject (no base class) in MFC Framework?

  注釋:CMainFrame類的基類順序以此是CMDIFrameWnd--〉CFrameWnd-->CWnd-->CCmdTarget-->CObject

//in Afx.h
// class CObject is the root of all compliant objects
 class AFX_NOVTABLE CObject
 {
   public:
   virtual CRuntimeClass* GetRuntimeClass() const;
   static const CRuntimeClass classCObject;
   ...//
 }
 
//in objcore.cpp
 // special runtime-class structure for CObject (no base class)
 const struct CRuntimeClass CObject::classCObject =
 { "CObject", sizeof(CObject), 0xffff, NULL, NULL, NULL };

 CRuntimeClass* CObject::GetRuntimeClass() const
 {
 return _RUNTIME_CLASS(CObject);
 }
 
                       ///////////////////////////////////////////////////////
                       /* 一.4.執行期類型識別網的應用 */
                       //////////////////////////////////////////////////////
    執行期類型識別網建立好了,它將在MFC Framework中發揮重要作用,這里舉一個其應用的例子:
    CObject::IsKindOf函數就是利用該網完成的函數。下面看看其源代碼:
  //in objcore.cpp
  BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const
  {
 ASSERT(this != NULL);
 // it better be in valid memory, at least for CObject size
 ASSERT(AfxIsValidAddress(this, sizeof(CObject)));
        // simple SI case
 CRuntimeClass* pClassThis = GetRuntimeClass();
 return pClassThis->IsDerivedFrom(pClass);
  }
  BOOL CRuntimeClass::IsDerivedFrom(const CRuntimeClass* pBaseClass) const
 {
 ASSERT(this != NULL);
 ASSERT(AfxIsValidAddress(this, sizeof(CRuntimeClass), FALSE));
 ASSERT(pBaseClass != NULL);
 ASSERT(AfxIsValidAddress(pBaseClass, sizeof(CRuntimeClass), FALSE));

 // simple SI case
 const CRuntimeClass* pClassThis = this;
   #ifdef _AFXDLL
 for (;;)
   #else
 while (pClassThis != NULL)
   #endif
 {
  if (pClassThis == pBaseClass)
   return TRUE;
   #ifdef _AFXDLL
  if (pClassThis->m_pfnGetBaseClass == NULL)
   break;
  pClassThis = (*pClassThis->m_pfnGetBaseClass)();
   #else
  pClassThis = pClassThis->m_pBaseClass;
   #endif
 }
 return FALSE;       // walked to the top, no match
}

                       //////////////////////////////////////////////////
                       /*  二.1. 執行期動態創建技術   */
                       //////////////////////////////////////////////////
   談完了執行期類型識別網建立后,就來看看另一項重要的技術-----執行期動態創建技術 ,該技術應用可謂是甚廣,在你的SDI中的主框架,視圖和其對應的文檔以及MDI中的子框架,視圖和其對應的文檔都是利用動態創建技術生成的。
   執行期動態創建技術利用的也是CRuntimeClass結構和一對對應的宏DECLARE_DYNCREATE(class_name)
和IMPLEMENT_DYNCREATE(class_name, base_class_name);
   下面看看這兩個宏的定義吧:

   #define DECLARE_DYNCREATE(class_name) \
 DECLARE_DYNAMIC(class_name) \
 static CObject* PASCAL CreateObject();
   #define IMPLEMENT_DYNCREATE(class_name, base_class_name) \
 CObject* PASCAL class_name::CreateObject() \
  { return new class_name; } \
 IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, \
  class_name::CreateObject, NULL)
   應該看出來執行期類型識別網是執行期動態創建技術的基礎。
                    
                       ///////////////////////////////////////////////////////////
                       /* 二.2 執行期動態創建技術組成部分*/
                       ///////////////////////////////////////////////////////////
                      
   下面將列出與執行期動態創建技術有關的CRuntimeClass的結構成員:
    // object type information  
   struct CRuntimeClass
   {
       CObject* (PASCAL* m_pfnCreateObject)(); // NULL => abstract class
       CObject* CreateObject();
       ...//
   };
  
                       ////////////////////////////////////
                       /*      二.3.宏展開       */
                       ////////////////////////////////////                 
   這回我們以SDI程序中的CMainFrame的動態創建為例,下面看看上面的兩個宏在xx.h和xx.cpp文件中展開后的樣子:
   //in MainFrm.h
   class CMainFrame
   { 
      public:
        static const CRuntimeClass classCMainFrame;
 virtual CRuntimeClass* GetRuntimeClass() const;
        static CObject* PASCAL CreateObject();
        ...//
   };
   //in MainFrm.cpp
    CObject* PASCAL CMainFrame::CreateObject() { return new class_name; }
    AFX_COMDAT const CRuntimeClass CMainFrame::classCMainFrame    ={
CMainFrame,sizeof(classCMainFrame),0xFFFF,CMainFrame::CreateObject,(CRuntimeClass*)(&CMDIFrameWnd::classCMDIFrameWnd),NULL,NULL};

    CRuntimeClass* CMainFrame::GetRuntimeClass() const
  { return &CMainFrame::classCMainFrame; }
    看出來著兩個宏展開后與前面介紹的那兩個宏的不同了吧;DECLARE_DYNCREATE在頭文件中加入了一個函數static CObject* PASCAL CreateObject();IMPLEMENT_DYNCREATE的展開也有所不同。下面將詳述。
 
 
                         ////////////////////////////////////////////
                         /* 二.4.如何進行動態創建  */
                         ///////////////////////////////////////////
    讓我們看看CMainFrame的構造函數的access control吧!protected:疑惑了吧?受保護的構造函數是不能夠得實例化的。那么CMainFrame是如何被構造出來的呢?這就是微軟利用CRuntimeClass進行動態創建的原因。下面我用一個簡單的例子來詮釋一下構造方法:
   //in A.h
   class A
   {
      protected:A(){}
                ...//something else
      public:static A*CreateObject();
   };
   //in A.cpp
   A*A::CreateObject()
   {  return new A();}
   //in test.cpp
   int main(void)
   {
      A*pNewObj=A::CreateObject();//OK
      return 0;
   }
   詮釋完了后就讓我們一一對應的看看微軟是如何做的吧,我們回頭再看看DECLARE_DYNCREATE為CMainFrame
添加了什么吧。static CObject* PASCAL CreateObject(); 眼睛亮了吧!是的它就相當于上個例子中的 
static A*CreateObject();那么是誰調用了它呢?再回頭看看IMPLEMENT_DYNCREATE作了什么吧?

AFX_COMDAT const CRuntimeClass CMainFrame::classCMainFrame    ={
CMainFrame,sizeof(classCMainFrame),0xFFFF,CMainFrame::CreateObject,(CRuntimeClass*)(&CFrameWnd::classFrameWnd),NULL,NULL};
   原來該宏把m_pfnCreateObject賦值為CMainFrame::CreateObject;
   說到這你可能還是不很清楚,那么讓我們看看MFC的代碼吧!
    CSingleDocTemplate* pDocTemplate;
 pDocTemplate = new CSingleDocTemplate(
  IDR_MAINFRAME,
  RUNTIME_CLASS(CMyDoc),
  RUNTIME_CLASS(CMainFrame),       // 主 SDI 框架窗口
  RUNTIME_CLASS(CMyView));
    我們在MFC技術內幕系列之(二)----《MFC文檔視圖結構內幕 》中曾經說過,所以這里不詳述,
    CSingleDocTemplate::OpenDocumentFile調用了CreateNewFrame
    CFrameWnd* CDocTemplate::CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther)//部分源代碼
    {
 ...//
       CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject();
        ...//
    }
    m_pFrameClass是CRuntimeClass*指針它指向CMainFrame::classCMainFrame;CreateNewFrame函數調用了
(CFrameWnd*)m_pFrameClass->CreateObject();而CObject* CRuntimeClass::CreateObject()代碼如下:
                  
  //in objcore.cpp
  CObject* CRuntimeClass::CreateObject()
 {
 if (m_pfnCreateObject == NULL)
 {
  TRACE(traceAppMsg, 0,
   _T("Error: Trying to create object which is not ")
   _T("DECLARE_DYNCREATE \nor DECLARE_SERIAL: %hs.\n"),
   m_lpszClassName);
  return NULL;
 }

 CObject* pObject = NULL;
 TRY
 {
  pObject = (*m_pfnCreateObject)();
 }
 END_TRY

 return pObject;
 }
  它調用了 (*m_pfnCreateObject)();即 CMainFrame::CreateObject();并返回了動態創建的 CMainFrame對象的指針。看到著你應該明白了吧。    
                       /////////////////////////////////////////
                       /*        三.下期預告         */
                       /////////////////////////////////////////
   MFC技術內幕系列之(四)-----《MFC消息映射與消息傳遞內幕》

posted on 2007-07-27 11:30 醒目西西 閱讀(652) 評論(0)  編輯 收藏 引用
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            免费试看一区| 欧美亚州在线观看| 欧美黑人在线播放| 久久久亚洲国产天美传媒修理工| 亚洲免费在线视频| 亚洲在线视频网站| 香蕉久久夜色精品| 欧美三级网址| 欧美日韩中文字幕在线视频| 欧美日韩1080p| 欧美午夜精品一区二区三区| 国产精品麻豆成人av电影艾秋| 欧美日韩国产专区| 国产精品自拍一区| 精品成人国产| 9i看片成人免费高清| 日韩午夜在线视频| 亚洲欧美视频在线观看| 欧美主播一区二区三区美女 久久精品人| 午夜视频一区在线观看| 久久精品三级| 亚洲日本电影在线| 日韩视频一区二区在线观看| 中文日韩在线视频| 久久久久久69| 欧美午夜在线视频| 在线免费观看欧美| 国产一区二区三区四区在线观看 | 亚洲欧美日韩在线不卡| 久久久久久久一区| 亚洲人成啪啪网站| 午夜日韩在线观看| 欧美日韩国产成人| 国内精品久久久久久久果冻传媒| 91久久精品国产91久久性色tv| 中文一区字幕| 欧美大片网址| 欧美亚洲在线观看| 欧美三级网址| 亚洲美洲欧洲综合国产一区| 欧美一区二区三区四区视频| 亚洲国产另类 国产精品国产免费| 亚洲免费视频观看| 欧美日韩另类视频| 亚洲电影免费观看高清| 欧美亚洲综合网| 亚洲免费av观看| 乱中年女人伦av一区二区| 国产精品午夜在线| 亚洲一区二区在线免费观看| 亚洲欧洲偷拍精品| 蜜桃视频一区| **性色生活片久久毛片| 久久精品99无色码中文字幕| 在线视频欧美精品| 欧美日韩在线亚洲一区蜜芽| 亚洲精品影视| 欧美刺激午夜性久久久久久久| 欧美一级视频免费在线观看| 国产精品国内视频| 国产精品一区在线播放| 国产日韩av一区二区| 亚洲日本在线观看| 欧美不卡高清| 免费中文日韩| 亚洲免费av观看| 亚洲电影在线观看| 美女黄毛**国产精品啪啪| 永久91嫩草亚洲精品人人| 久久青草久久| 免费看的黄色欧美网站| 亚洲黄色免费网站| 欧美v国产在线一区二区三区| 久久久不卡网国产精品一区| 狠狠色丁香婷婷综合久久片| 榴莲视频成人在线观看| 久久久视频精品| 亚洲欧洲免费视频| 99国产精品视频免费观看| 国产精品成人免费精品自在线观看| 一区二区三区久久网| 中日韩美女免费视频网站在线观看| 欧美特黄视频| 久久久.com| 欧美成人69| 亚洲欧美国产精品va在线观看| 亚洲一区视频| 在线国产精品播放| 日韩一区二区精品视频| 国产精品免费一区豆花| 久久五月激情| 欧美了一区在线观看| 亚洲影院免费观看| 欧美一级大片在线观看| 亚洲国产精品久久久久婷婷884| 亚洲人成在线观看| 国产女人水真多18毛片18精品视频| 久久艳片www.17c.com| 欧美激情1区2区3区| 欧美一区二区三区视频在线观看 | 欧美精品成人| 欧美一区二区三区婷婷月色| 久久精品国产一区二区电影| 日韩视频在线一区| 午夜国产精品影院在线观看| 亚洲国产精品黑人久久久| 99热在线精品观看| 黄色成人在线| 一区二区三区视频在线播放| 一区二区三区在线看| 99re这里只有精品6| 狠狠色噜噜狠狠狠狠色吗综合| 亚洲精品在线三区| 亚洲福利电影| 亚洲欧美在线aaa| 一本色道久久88综合日韩精品| 欧美在线视频免费| 亚洲图色在线| 欧美激情一区二区三区蜜桃视频 | 黄色成人在线观看| 在线一区二区日韩| 亚洲精品麻豆| 久久久视频精品| 久久精品国产视频| 国产精品色一区二区三区| 亚洲欧洲另类国产综合| 亚洲高清久久久| 久久国产精品72免费观看| 亚洲欧美日韩国产一区二区| 欧美激情亚洲精品| 亚洲国产女人aaa毛片在线| 在线免费精品视频| 久久久久久穴| 免费日韩一区二区| 亚洲国产你懂的| 久久久久中文| 欧美成人官网二区| 亚洲人在线视频| 欧美国产三级| 日韩视频在线观看免费| 一本色道久久综合狠狠躁篇的优点| 欧美本精品男人aⅴ天堂| 亚洲第一精品福利| 99精品视频免费观看| 欧美伦理一区二区| aa成人免费视频| 亚洲欧美在线另类| 国产欧美日韩不卡免费| 先锋影音一区二区三区| 久久久久综合| 亚洲第一中文字幕在线观看| 久久九九热免费视频| 久久综合九色| 欧美国产综合| 日韩视频免费观看高清在线视频 | 另类激情亚洲| 黄色一区三区| 久久精品亚洲精品国产欧美kt∨| 欧美亚洲午夜视频在线观看| 国产日韩在线视频| 欧美一区二区女人| 久久精品国产第一区二区三区最新章节| 欧美日韩综合久久| 蜜桃av噜噜一区| 夜色激情一区二区| 亚洲欧美三级伦理| 久久久www成人免费无遮挡大片 | 午夜天堂精品久久久久| 国产精品久久| 欧美一区在线直播| 久色成人在线| 亚洲成在人线av| 欧美国产欧美亚洲国产日韩mv天天看完整 | 欧美日韩在线高清| 一卡二卡3卡四卡高清精品视频| 日韩亚洲成人av在线| 午夜精品久久久久久99热软件| 久久综合综合久久综合| 亚洲国产精品久久久久秋霞蜜臀| 亚洲日本欧美日韩高观看| 91久久精品国产91久久| 国产精品久久久久久久电影| 性欧美精品高清| 蜜臀99久久精品久久久久久软件| 亚洲国产毛片完整版| 欧美日韩三级一区二区| 亚洲永久精品大片| 欧美wwwwww| 亚洲网站啪啪| 美女成人午夜| 欧美亚洲日本网站| 亚洲丶国产丶欧美一区二区三区 | 欧美在线综合视频| 亚洲国产成人精品久久久国产成人一区| 欧美成人蜜桃| 麻豆av一区二区三区久久| 亚洲乱码视频| 免费成人av资源网| 午夜激情亚洲| 亚洲一区二区在|