免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
技術(shù)資料-【MFC六大關(guān)鍵技術(shù)剖析之動(dòng)態(tài)創(chuàng)建】
【MFC六大關(guān)鍵技術(shù)剖析之動(dòng)態(tài)創(chuàng)建】
動(dòng)態(tài)創(chuàng)建就是運(yùn)行時(shí)創(chuàng)建指定類的對(duì)象,在MFC中大量使用。如框架窗口對(duì)象、視對(duì)象,還有文檔對(duì)象都需要由文檔模板類對(duì)象來動(dòng)態(tài)的創(chuàng)建。我覺得這是每個(gè)MFC的學(xué)習(xí)者很希望理解的問題。
初次接觸MFC的時(shí)候,很容易有這樣的迷惘。MFC的幾大類不用我們設(shè)計(jì)也就罷了,但最疑惑的是不用我們實(shí)例化對(duì)象。本來最直觀的理解就是,我們需要框架的時(shí)候,親手寫上CFrameWnd myFrame;需要視的時(shí)候,親自打上CView myView;……
但MFC不給我們這個(gè)機(jī)會(huì),致使我們錯(cuò)覺窗口沒有實(shí)例化就彈出來了!就象畫了張電視機(jī)的電路圖就可以看電視一樣令人難以置信。但大伙想了一下,可能會(huì)一拍腦門,認(rèn)為簡單不過:MFC自動(dòng)幫我們完成CView myView之流的代碼不就行了么!??!其實(shí)不然,寫MFC程序的時(shí)候,我們幾乎要對(duì)每個(gè)大類進(jìn)行派生改寫。換句話說,MFC并不知道我們打算怎樣去改寫這些類,當(dāng)然也不打算全部為我們“靜態(tài)”創(chuàng)建這些類了。即使靜態(tài)了創(chuàng)建這些類也沒有用,因?yàn)槲覀儚膩硪膊粫?huì)直接利用這些類的實(shí)例干什么事情。我們只知道,想做什么事情就往各大類里塞,不管什么變量、方法照塞,塞完之后,我們似乎并未實(shí)例化對(duì)象,程序就可以運(yùn)行!
要做到把自己的類交給MFC,MFC就用同一樣的方法,把不同的類一一準(zhǔn)確創(chuàng)建,我們要做些什么事情呢?同樣地,我們要建立鏈表,記錄各類的關(guān)鍵信息,在動(dòng)態(tài)創(chuàng)建的時(shí)候找出這些信息,就象上一節(jié)RTTI那樣!我們可以設(shè)計(jì)一個(gè)類:
struct CRuntimeClass{
LPCSTR m_lpszClassName; //類名指針
CObject* (PASCAL *m_pfnCreateObject)(); //創(chuàng)建對(duì)象的函數(shù)的指針
CRuntimeClass* m_pBaseClass; //講RTTI時(shí)介紹過
CRuntimeClass* m_pNextClass; //指向鏈表的下一個(gè)元素(許多朋友說上一節(jié)講RTTI時(shí)并沒有用到這個(gè)指針,我原本以為這樣更好理解一些,因?yàn)闆]有這個(gè)指針,這個(gè)鏈表是無法連起來,而m_pBaseClass僅僅是向基類走,在MFC的樹型層次結(jié)構(gòu)中m_pBaseClass是不能遍歷的)
CObject* CreateObject(); //創(chuàng)建對(duì)象
static CRuntimeClass* PASCAL Load(); //遍歷整個(gè)類型鏈表,返回符合動(dòng)態(tài)創(chuàng)建的對(duì)象。
static CRuntimeClass* pFirstClass; //類型鏈表的頭指針
};
一下子往結(jié)構(gòu)里面塞了那么多的東西,大家可以覺得有點(diǎn)頭暈。至于CObject* (PASCAL *m_pfnCreateObject)();,這定義函數(shù)指針的方法,大家可能有點(diǎn)陌生。函數(shù)指針在C++書籍里一般被定為選學(xué)章節(jié),但MFC還是經(jīng)常用到此類的函數(shù),比如我們所熟悉的回調(diào)函數(shù)。簡單地說m_pfnCreateObject即是保存了一個(gè)函數(shù)的地址,它將會(huì)創(chuàng)建一個(gè)對(duì)象。即是說,以后,m_pfnCreateObject指向不同的函數(shù),我們就會(huì)創(chuàng)建不同類型的對(duì)象。
有函數(shù)指針,我們要實(shí)現(xiàn)一個(gè)與原定義參數(shù)及返回值都相同一個(gè)函數(shù),在MFC中定義為:
static CObject* PASCAL CreateObject(){return new XXX};//XXX為類名。類名不同,我們就創(chuàng)建不同的對(duì)象。
由此,我們可以如下構(gòu)造CRuntimeClass到鏈表:
CRuntimeClass classXXX={
類名,
……,
XXX::CreateObject(), //m_pfnCreateObject指向的函數(shù)
RUNTIME_CLASS(基類名) // RUNTIME_CLASS宏可以返回CRuntimeClass對(duì)象指針。
NULL //m_pNextClass暫時(shí)為空,最后會(huì)我們再設(shè)法讓它指向舊鏈表表頭。
};
這樣,我們用函數(shù)指針m_pfnCreateObject(指向CreateObject函數(shù)),就隨時(shí)可new新對(duì)象了。并且大家留意到,我們在設(shè)計(jì)CRuntimeClass類對(duì)時(shí)候,只有類名(和基類名)的不同(我們用XXX代替的地方),其它的地方一樣,這正是我們想要的,因?yàn)槲覀儎?dòng)態(tài)創(chuàng)建也象RTTI那樣用到兩個(gè)宏,只要傳入類名和基類作宏參數(shù),就可以滿足條件。
即是說,我們類說明中使用DECLARE_DYNCREATE(CLASSNMAE)宏和在類的實(shí)現(xiàn)文件中使用IMPLEMENT_DYNCREATE(CLASSNAME,BASECLASS)宏來為我們加入鏈表,至于這兩個(gè)宏怎么為我們建立一個(gè)鏈表,我們自己可以玩玩文字代換的游戲,在此不一一累贅。但要說明的一點(diǎn)就是:動(dòng)態(tài)創(chuàng)建宏xxx_DYNCREATE包含了RTTI宏,即是說, xxx_DYNCREATE是xxx_DYNAMIC的“增強(qiáng)版”。
到此,我們有必要了解一下上節(jié)課沒有明講的m_pNextClass指針。因?yàn)镸FC層次結(jié)構(gòu)是樹狀的,并不是直線的。如果我們只有一個(gè)m_pBaseClass指針,它只會(huì)沿著基類上去,會(huì)漏掉其它分支。在動(dòng)態(tài)創(chuàng)建時(shí),必需要檢查整個(gè)鏈表,看有多少個(gè)要?jiǎng)討B(tài)創(chuàng)建的對(duì)象,即是說要從表頭(pFirstClass)開始一直遍歷到表尾(m_pNextClass=NULL),不能漏掉一個(gè)CRuntimeClass對(duì)象。
所以每當(dāng)有一個(gè)新的鏈表元素要加入鏈表的時(shí)候,我們要做的就是使新的鏈表元素成為表頭,并且m_pNextClass指向原來鏈表的表頭,即像下面那樣(當(dāng)然,這些不需要我們操心,是RTTI宏幫助我們完成的):
pNewClass->m_pNextClass=CRuntimeClass::pFirstClass;//新元素的m_pNextClass指針指向想加入的鏈表的表頭。
CRuntimeClass::pFirstClass=pNewClass;//鏈表的頭指針指向剛插入的新元素。
好了,有了上面的鏈表,我們就可以分析動(dòng)態(tài)創(chuàng)建了。
有一了張有類名,函數(shù)指針,動(dòng)態(tài)創(chuàng)建函數(shù)的鏈表,我們就可以知道應(yīng)該按什么步驟去動(dòng)態(tài)創(chuàng)建了:
1、獲得一要?jiǎng)討B(tài)創(chuàng)建的類的類名(假設(shè)為A)。
2、將A跟鏈表里面每個(gè)元素的m_lpszClassName指向的類名作比較。
3、若找到跟A相同的類名就返回A所屬的CRuntimeClass元素的指針。
4、判斷m_pfnCreateObject是否有指向創(chuàng)建函數(shù),有則創(chuàng)建對(duì)象,并返回該對(duì)象。
代碼演示如下(以下兩個(gè)函數(shù)都是CRuntimeClass類函數(shù)):
///////////////以下為根據(jù)類名從表頭向表尾查找所屬的CRuntimeClass對(duì)象////////////
CRuntimeClass* PASCAL CRuntimeClass::Load()
{
char szClassXXX[64];
CRuntimeClass* pClass;
cin>>szClassXXX; //假定這是我們希望動(dòng)態(tài)創(chuàng)建的類名
for(pClass=pFirstClass;pClass!=NULL;pClass=pClass->m_pNextClass)
{
if(strcmp(szClassXXX,pClass->m_lpszClassName)==0)
return pClass;
}
return NULL
}
///////////根據(jù)CRuntimeClass創(chuàng)建對(duì)象///////////
CObject* CRuntimeClass::CreateObject()
{
if(m_pfnCreateObject==NULL) return NULL;
CObject *pObject;
pObject=(* m_pfnCreateObject)(); //函數(shù)指針調(diào)用
return pObject;
}
有了上面兩個(gè)函數(shù),我們在程序執(zhí)行的時(shí)候調(diào)用,就可以動(dòng)態(tài)創(chuàng)建對(duì)象了。
我們還可以更簡單地實(shí)現(xiàn)動(dòng)態(tài)創(chuàng)建,大家注意到,就是在我們的程序類里面有一個(gè)RUNTIME_CLASS(class_name)宏,這個(gè)宏在MFC里定義為:
RUNTIME_CLASS(class_name) ((CRuntimeClass*)(&class_name::class##class_name))
作用就是得到類的RunTime信息,即返回class_name所屬CRuntimeClass的對(duì)象。在我們的應(yīng)用程序員類(CMyWinApp)的InitInstance()函數(shù)下面的CSingleDocTemplate函數(shù)中,有:
RUNTIME_CLASS(CMyDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CMyView)
構(gòu)造文檔模板的時(shí)候就用這個(gè)宏得到文檔、框架和視的RunTime信息。有了RunTime信息,我們只要一條語句就可以動(dòng)態(tài)創(chuàng)建了,如:
classMyView->CreateObject(); //對(duì)象直接調(diào)用用CRuntimeClass本身的CreateObject()
現(xiàn)在,細(xì)心的朋友已經(jīng)能清楚動(dòng)態(tài)創(chuàng)建需要的步驟:
1、定義一個(gè)不帶參數(shù)的構(gòu)造函數(shù)(默認(rèn)構(gòu)造函數(shù));因?yàn)槲覀兪怯肅reateObject()動(dòng)態(tài)創(chuàng)建,它只有一條語句就是return new XXX,不帶任何參數(shù)。所以我們要有一個(gè)無參構(gòu)造函數(shù)。
2、類說明中使用DECLARE_DYNCREATE(CLASSNMAE)宏;和在類的實(shí)現(xiàn)文件中使用IMPLEMENT_DYNCREATE(CLASSNAME,BASECLASS)宏;這個(gè)宏完成構(gòu)造CRuntimeClass對(duì)象,并加入到鏈表中。
3、使用時(shí)先通過宏RUNTIME_CLASS得到類的RunTime信息,然后使用CRuntimeClass的成員函數(shù)CreateObject創(chuàng)建一個(gè)該類的實(shí)例。
4、CObject* pObject = pRuntimeClass->CreateObject();//完成動(dòng)態(tài)創(chuàng)建。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
第三章 CObject類
CObject作用
MFC淺析(4) CObject淺析
MFC序列化-IMPLEMENT_SERIAL(...)
DYNAMIC
C++動(dòng)態(tài)創(chuàng)建對(duì)象應(yīng)用技術(shù)講解
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服