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

依舊的博客

技術學習

C++博客 首頁 新隨筆 聯系 聚合 管理
  17 Posts :: 1 Stories :: 2 Comments :: 0 Trackbacks

我們知道MFC的作用在于封裝Windows的編程接口,并提供應用程序框架的開發模式。為了完成從前者到后者的過渡,MFC實現了幾種基本機制,它們是消息映射,命令傳遞,運行時類信息(RTCI),動態創建和序列化。

消息映射和命令傳遞是對SDK程序交互機制的封裝。序列化是應用程序需要的一種基本特性,即把數據保存到磁盤和從磁盤打開數據。通過RTCI和動態創建,可以把軟件的對象數據保存到磁盤,反過來從這些數據識別和恢復對象,從而實現對象的序列化。基于數據庫的序列化機制和這種方式不同,應用程序和數據庫之間有一個約定,以什么樣的格式保存什么樣的數據,再以同樣的方式打開,并且如何重建對象數據也定下來了,在打開數據時,應用程序不需要有適應性,不需要識別數據類型,也不需要根據在運行期才確定的類型名稱創建其對象。

動態創建就是創建某種類型的對象,具體類型在運行時確定,編譯時可能不知道。比如運行時用戶輸入一個類型名稱,如果該類型是程序類型體系中的一員,則程序中將能夠創建該類型的對象。下面的代碼是使用MFC動態創建機制的一個簡化的例子:

CRuntimeClass* g_pFirstClass;
void func()
{
     char szClassName[64];
     CRuntimeClass* pClass;
     CObject* pObject;
    
     cout << "enter a class name...  ";
     cin >> szClassName;
    
     for (pClass = g_pFirstClass; pClass != NULL; pClass = pClass->m_pNextClass)
     {
          if (strcmp(szClassName, pClass->m_lpszClassName) == 0)
              pObject = pClass->CreateObject();
     }
}

實現動態創建的思路是把動態的類型名稱與程序類型體系中的每一個進行比較,與某個類型吻合時讓該類型創建自身的對象。這樣,支持動態創建的類庫中的每一個類都要額外實現一些功能,即判別一個名稱是否與自身相符,以及創建自身的對象。

判別一個名稱是否與自身相符,這是運行時類識別的內容,所以MFC動態創建是在RTCI基礎上實現的。

RTCI是一個對象能夠判定自己是否屬于某種類型,該類型的名稱在運行時確定,編譯時可能不知道。從下面的例子很容易理解RTCI,

void Func()
{
     char szClassName[64];
     CDocument* pDoc = new CDocument;
    
     cout << "enter a class name...  ";
     cin >> szClassName;
    
     cout << pDoc->IsKindOf(szClassName); //是返回1,否返回0
}

有一點需要說明的是,因為CDocument派生于CObject,所以IsKindOf對于CObject也要返回1。因為我們是從動態創建出發的,所以如果是這樣可能會有一點背離初衷。但是RTCI明顯和動態創建有密切聯系,RTCI也可能有單獨的價值,所以先把RTCI實現起來。

實現RTCI的思路是讓每一個類記錄自身的類型信息,并提供IsKindOf(char*)函數進行所給類型與自身類型的比較,而且還要能訪問基類的類型信息,進行比較,一直到根類。所以記錄的類型信息要按繼承關系連起來,每個類的IsKindOf()還要調用基類的IsKindOf()。MFC把要記錄的類型信息抽取到一個CRuntimeClass結構體中,每個類中加入一個CRuntimeClass成員即可。

現在回到動態創建,在RTCI建立的數據結構基礎上將可實現它。動態創建從不同于IsKindOf()的角度使用這一數據結構,它要遍歷所有類型的CRuntimeClass。那么僅僅有繼承關系的類的CRuntimeClass相連還不夠,要把所有類的CRuntimeClass連成一個鏈表。其實動態創建并不關心類間的繼承關系,它平等看待每個類。現在以CRuntimeClass為結點構成一個縱橫兩個方向的鏈表,IsKindOf()和動態創建分別使用它不同的側面。

序列化的概念是在文件中存儲對象信息,并能根據它恢復對象。對于文檔視圖結構的軟件,用戶需要保存所編輯的文檔和打開已編輯的文檔,這正是序列化的應用,所以序列化是非常重要的一種特性。在序列化恢復對象時,就可以用到動態創建。

使用MFC序列化的例子如下,

void CMyDocument::Serialize(CArichive &ar)
{
    if (ar.IsStoring())
    {
        ar << m_pMyClass; //CMyClass m_pMyClass;
    }
    else
    {
        ar >> m_pMyClass;
    }
}

一個支持序列化的類提供Serialize(CArchive &)函數,重載<<和>>操作。注意兩者是不同的,在上例中,CMyDocument類的信息并不被序列化,而CMyClass類的信息被序列化。實際上一個序列化類的<<和>>操作,其不涉及類信息的部分是調用Serialize()完成的,它必須同時實現這兩者。

按照MFC的要求,需要在支持序列化的類定義中使用DECLARE_SERIAL宏,在類實現中使用IMPLEMENT_SERIAL宏。我們看一下這兩個宏實現了什么,

#define DECLARE_SERIAL(class_name) \
 _DECLARE_DYNCREATE(class_name) \
 AFX_API friend CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb);

#define IMPLEMENT_SERIAL(class_name, base_class_name, wSchema) \
 CObject* PASCAL class_name::CreateObject() \
  { return new class_name; } \
 _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, \
  class_name::CreateObject) \
 AFX_CLASSINIT _init_##class_name(RUNTIME_CLASS(class_name)); \
 CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb) \
  { pOb = (class_name*) ar.ReadObject(RUNTIME_CLASS(class_name)); \
   return ar; } \

主要是加入了對>>的重載,但是沒有重載<<,MFC僅提供了CObject對<<的重載,如下,

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

這是因為在序列化讀和寫的時候,都需要具體類的CRuntimeClass信息。相應的GetRuntimeClass()是一個虛函數,CObject重載<<,在寫類信息時調用到該函數,由于虛函數機制,寫入的是具體類的信息。但是這里隱含著一個條件,就是調用<<和GetRuntimeClass()時,具體類對象已經存在了,而調用>>和讀入類信息時,該類對象還未被創建,所以無法利用這種機制,只能在每個具體類中都重載一次>>。我覺得《深入解析MFC》對這個問題的解釋不正確。

這里有一個問題需要明確一下,序列化為什么要寫入類信息?一是它應該保存完整的能夠獨立恢復對象的信息,二是在程序讀入對象時,要把它的類信息和程序中期望的(所能處理的)類信息相比較,進行檢驗。

看IMPLEMENT_SERIAL宏對重載>>的實現,是提供一個期望的CRuntimeClass結構(用于檢驗),委托CArchive進行對象讀取。因為讀對象時首先要跟文件打交道,所以交給CArchive處理,隨后把讀出的數據寫入對象時,CArchive再調用具體類的Serialize(),如此合作是十分恰當的。在這里,CArchive還負責了讀出和檢驗類信息,然后創建對象的過程。因為一方面具體類對象還不存在,另一方面這些操作對所有具體類都沒有分別,應該提出來,在類級別實現或者讓合作者實現。實際上,MFC先把這個過程交給CArchive::ReadClass(),后者又調用CRuntimeClass::Load()。 

對于序列化來說,搞清它的概念以后,就是實現Serialzie(),重載<<和>>。對<<和>>的重載涉及很多工作,MFC已經幫我們實現了,我們也看見了大概的設計,主要是與CArchive分工合作,其次是CRuntimeClass。

現在看到CRuntimeClass結構體在MFC對RTCI,動態創建和序列化的實現中都起著重要的作用,重新認識一下這個數據結構很有必要。

CRuntimeClass包含了關于類的各種信息和有關操作。把類及其基類的CRuntimeClass連成一個鏈表,就可以很方便地實現RTCI的IsKindOf();把所有類的CRuntimeClass連成一個鏈表,再加上一個簡單的CreateObject函數,就可以對以任意類名進行動態創建的企圖做出反應;CRuntimeClass還實現了向文件讀寫類信息的Load(),Store(),配合序列化的實現。

在分析消息映射和命令傳遞機制之前,需要對Windows程序模型有很好的理解。

未完待續...


參考:

《深入解析MFC》/中國電力出版社
《深入淺出MFC》/華中科大出版社
《Windows程序設計》/北大出版社

posted on 2006-05-15 19:33 依舊的博客 閱讀(1191) 評論(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>
            亚洲欧美日韩国产综合在线| 亚洲视频欧洲视频| 亚洲永久字幕| 老色批av在线精品| 在线一区二区三区四区| 亚洲国产成人在线视频| 国产视频一区在线观看| 欧美巨乳在线观看| 久色婷婷小香蕉久久| 欧美亚洲一区二区在线观看| 在线综合亚洲| 亚洲自拍三区| 久久久久国产精品厨房| 久久久久久9999| 女仆av观看一区| 欧美日韩国产一区二区| 欧美日韩亚洲系列| 国产精品美女久久久久av超清| 欧美日韩美女一区二区| 欧美亚韩一区| 亚洲国产一二三| 亚洲一二区在线| 久久久亚洲影院你懂的| 亚洲大片免费看| 亚洲国产美国国产综合一区二区| 欧美成人一品| 午夜精品成人在线| 欧美黄网免费在线观看| 国产精品视频午夜| 亚洲伦理一区| 欧美aⅴ一区二区三区视频| 亚洲精品一二三| 久久久久久夜精品精品免费| 亚洲高清资源综合久久精品| 一级成人国产| 欧美日本高清| 一区二区三区四区蜜桃| 欧美 日韩 国产一区二区在线视频| 亚洲美女区一区| 免费短视频成人日韩| 国产一区二区精品在线观看| 小处雏高清一区二区三区| 日韩视频在线观看国产| 久久男人av资源网站| 国产亚洲在线观看| 久久精品日产第一区二区| 午夜精品久久久久久久久| 国产精品国产三级国产aⅴ浪潮| 亚洲人成网站在线观看播放| 欧美成人xxx| 欧美日韩亚洲一区| 欧美伊人影院| 欧美在线视频一区二区| 国产揄拍国内精品对白| 欧美一区二区视频97| 欧美在线观看一区| 日韩视频不卡| 亚洲欧美成人一区二区在线电影| 欧美日韩视频专区在线播放| 欧美一区三区三区高中清蜜桃| 午夜亚洲精品| 亚洲国产成人午夜在线一区| 亚洲精品在线视频观看| 狠狠入ady亚洲精品| 亚洲日韩欧美一区二区在线| 欧美午夜视频在线观看| 久久精品国产亚洲a| 欧美日韩欧美一区二区| 国产精品乱码一区二区三区| 久久精品国产久精国产一老狼 | 欧美日韩国产丝袜另类| 亚洲欧美影音先锋| 欧美va亚洲va香蕉在线| 欧美一区二区三区免费观看视频| 久久久久久免费| 久久久水蜜桃| 国产精品美女久久久浪潮软件 | 亚洲美女色禁图| 久久www成人_看片免费不卡 | 欧美激情中文字幕在线| 久久精品日产第一区二区| 国产精品久久久91| 亚洲视频你懂的| 久久国产天堂福利天堂| 国产精品蜜臀在线观看| 在线一区二区三区四区| 这里只有精品电影| 欧美日韩免费观看一区三区 | 久久青青草综合| 亚洲国产va精品久久久不卡综合| 欧美一区二区三区免费观看视频| 午夜精品一区二区三区在线视| 国产欧美日韩三级| 欧美在线观看www| 亚洲国产经典视频| 亚洲一级二级| 在线免费观看一区二区三区| 欧美激情导航| 在线午夜精品| 国产夜色精品一区二区av| 欧美永久精品| 日韩一级视频免费观看在线| 欧美伊人久久久久久午夜久久久久| 国产一区二区三区丝袜| 欧美多人爱爱视频网站| 欧美一区二区三区免费看 | 欧美一区日本一区韩国一区| 精品电影在线观看| 国产精品不卡在线| 欧美 日韩 国产精品免费观看| 亚洲永久视频| 亚洲影视在线播放| 一区二区三区欧美亚洲| 亚洲国产成人91精品| 久久精品国产亚洲一区二区三区 | 欧美中文字幕在线播放| 亚洲激情电影中文字幕| 亚洲第一中文字幕| 欧美成人午夜视频| 欧美顶级少妇做爰| 美女日韩在线中文字幕| 久久九九免费视频| 久久婷婷国产综合精品青草 | 亚洲第一中文字幕| 国产香蕉97碰碰久久人人| 国产精品劲爆视频| 国产婷婷色一区二区三区| 国产精品久久久爽爽爽麻豆色哟哟| 欧美日韩国产三级| 国产欧美精品xxxx另类| 狠狠色丁香久久婷婷综合_中| 国产一区二区三区四区在线观看 | 欧美va天堂| 欧美国产日韩在线观看| 欧美区亚洲区| 国产午夜精品久久久| 亚洲大黄网站| 亚洲男人的天堂在线观看| 久久九九电影| 亚洲无线视频| 免费在线欧美黄色| 国产精品xnxxcom| 亚洲精品美女在线| 久久久精品国产99久久精品芒果| 模特精品裸拍一区| 亚洲在线视频免费观看| 免费观看亚洲视频大全| 国产精品热久久久久夜色精品三区 | 国产曰批免费观看久久久| 日韩一本二本av| 久久一区二区三区四区| 在线亚洲+欧美+日本专区| 欧美国产日本高清在线| 国产一区二区在线观看免费播放 | 亚洲欧美国产不卡| 久久在线播放| 久久精品国产精品| 黑人操亚洲美女惩罚| 香蕉国产精品偷在线观看不卡| 亚洲欧洲在线播放| 欧美成人免费va影院高清| 一区二区三区在线视频观看| 欧美一区二区三区四区在线观看地址 | 国产区日韩欧美| 午夜在线一区| 欧美在线视频二区| 国产日韩欧美二区| 欧美一区二区三区在线观看| 亚洲一区二区三区精品在线观看| 欧美日韩在线电影| 午夜精品久久久久久久99热浪潮| 日韩午夜av| 国产嫩草一区二区三区在线观看| 欧美亚洲一区二区在线| 久久电影一区| 亚洲欧洲精品一区二区三区不卡 | 亚洲欧美成人在线| 激情一区二区| 亚洲精品一区二区三区av| 国产精品激情电影| 欧美成黄导航| 国产视频不卡| 亚洲精品在线三区| 极品av少妇一区二区| 一本色道久久综合亚洲精品不卡| 国产精品三上| 亚洲毛片视频| 国产一区观看| 亚洲一区二区三区四区五区午夜| 一区免费观看视频| 午夜久久福利| 亚洲午夜视频| 欧美精品aa| 一本到高清视频免费精品| 在线观看欧美| 久久久999精品免费| 欧美一区二区视频在线| 亚洲国产合集| 夜夜狂射影院欧美极品| 欧美精品v日韩精品v韩国精品v |