追根究底, 六大關鍵技術剖析(第三部分)

2021-05-04 17:15:54 字數 4626 閱讀 6133

三、動態建立

動態建立就是執行時建立指定類的物件,在

mfc 中大量使用。如框架視窗物件、視物件,還有文件物件都需要由文件模板類物件來動態的建立。我覺得這是每個

mfc 的學習者很希望理解的問題。

初次接觸

mfc 的時候,很容易有這樣的迷惘。

mfc 的幾大類不用我們設計也就罷了,但最疑惑的是不用我們例項化物件。本來最直觀的理解就是,我們需要框架的時候,親手寫上

cframewnd myframe

;需要視的時候,親自打上

cview myview;

…… 但mfc

不給我們這個機會,致使我們錯覺視窗沒有例項化就彈出來了!就象畫了張電視機的電路圖就可以看電視一樣令人難以置信。但大夥想了一下,可能會一拍腦門,認為簡單不過:

mfc 自動幫我們完成

cview myview

之流的**不就行了麼!!!其實不然,寫

mfc 程式的時候,我們幾乎要對每個大類進行派生改寫。換句話說,

mfc 並 不知道我們打算怎樣去改寫這些類,當然也不打算全部為我們「靜態」建立這些類了。即使靜態了建立這些類也沒有用,因為我們從來也不會直接利用這些類的例項 幹什麼事情。我們只知道,想做什麼事情就往各大類裡塞,不管什麼變數、方法照塞,塞完之後,我們似乎並未例項化物件,程式就可以執行!

要做到把自己的類交給

mfc ,

mfc 就用同一樣的方法,把不同的類一一準確建立,我們要做些什麼事情呢?同樣地,我們要建立鍊錶,記錄各類的關鍵資訊,在動態建立的時候找出這些資訊,就象上一節

rtti

那樣!我們可以設計乙個類:

struct cruntimeclass;

一下子往結構裡面塞了那麼多的東西,大家可以覺得有點頭暈。至於

cobject* (pascal *m_pfncreateobject)();

,這定義函式指標的方法,大家可能有點陌生。函式指標在

c++ 書籍裡一般被定為選學章節,但

mfc 還是經常用到此類的函式,比如我們所熟悉的**函式。簡單地說

m_pfncreateobject

即是儲存了乙個函式的位址,它將會建立乙個物件。即是說,以後,

m_pfncreateobject

指向不同的函式,我們就會建立不同型別的物件。

有函式指標,我們要實現乙個與原定義引數及返回值都相同乙個函式,在

mfc 中定義為:

static cobject* pascal createobject();//***

為類名。類名不同,我們就建立不同的物件。

由此,我們可以如下構造

cruntimeclass

到鍊錶:

cruntimeclass class***=;

這樣,我們用函式指標

m_pfncreateobject

(指向createobject

函式),就隨時可

new 新物件了。並且大家留意到,我們在設計

cruntimeclass

類對時候,只有類名(和基類名)的不同(我們用

*** 代替的地方),其它的地方一樣,這正是我們想要的,因為我們動態建立也象

rtti

那樣用到兩個巨集,只要傳入類名和基類作巨集引數,就可以滿足條件。

即是說,我們類說明中使用

declare_dyncreate

(classnmae

)巨集和在類的實現檔案中使用

implement_dyncreate

(classname

,baseclass

)巨集來為我們加入鍊錶,至於這兩個巨集怎麼為我們建立乙個鍊錶,我們自己可以玩玩文字代換的遊戲,在此不一一累贅。但要說明的一點就是:動態建立巨集

***_dyncreate

包含了rtti

巨集,即是說,

***_dyncreate

是***_dynamic

的「增強版」。

到此,我們有必要了解一下上節課沒有明講的

m_pnextclass

指標。因為

mfc 層次結構是樹狀的,並不是直線的。如果我們只有乙個

m_pbaseclass

指標,它只會沿著基類上去,會漏掉其它分支。在動態建立時,必需要檢查整個鍊錶,看有多少個要動態建立的物件,即是說要從表頭(

pfirstclass

)開始一直遍歷到表尾(

m_pnextclass=null

),不能漏掉乙個

cruntimeclass

物件。所以每當有乙個新的鍊錶元素要加入鍊錶的時候,我們要做的就是使新的鍊錶元素成為表頭,並且

m_pnextclass

指向原來鍊錶的表頭,即像下面那樣(當然,這些不需要我們操心,是

rtti

巨集幫助我們完成的):

pnewclass->m_pnextclass=cruntimeclass::pfirstclass;//

新元素的

m_pnextclass

指標指向想加入的鍊錶的表頭。

cruntimeclass::pfirstclass=pnewclass;//

鍊錶的頭指標指向剛插入的新元素。

好了,有了上面的鍊錶,我們就可以分析動態建立了。

有一了張有類名,函式指標,動態建立函式的鍊錶,我們就可以知道應該按什麼步驟去動態建立了:

1 、獲得一要動態建立的類的類名(假設為

a )。

2 、將

a 跟鍊錶裡面每個元素的

m_lpszclassname

指向的類名作比較。

3 、若找到跟

a 相同的類名就返回

a 所屬的

cruntimeclass

元素的指標。

4 、判斷

m_pfncreateobject

是否有指向建立函式,有則建立物件,並返回該物件。**演示如下(以下兩個函式都是

cruntimeclass

類函式):

///以下為根據類名從表頭向表尾查詢所屬的

cruntimeclass

物件 cruntimeclass* pascal cruntimeclass::load()

return null

} /// 根據

cruntimeclass

建立物件

///

cobject* cruntimeclass::createobject()

有了上面兩個函式,我們在程式執行的時候呼叫,就可以動態建立物件了。

我們還可以更簡單地實現動態建立,大家注意到,就是在我們的程式類裡面有乙個

runtime_class(class_name)

巨集,這個巨集在

mfc 裡定義為:

runtime_class(class_name)   ((cruntimeclass*)(&class_name::class##class_name))

作用就是得到類的

runtime

資訊,即返回

class_name

所屬cruntimeclass

的物件。在我們的應用程式設計師類

的initinstance()

函式下面的

csingledoctemplate

函式中,有:

runtime_class(cmydoc),

runtime_class(cmainframe),       // main sdi frame window

runtime_class(cmyview)

構造文件模板的時候就用這個巨集得到文件、框架和視的

runtime

資訊。有了

runtime

資訊,我們只要一條語句就可以動態建立了,如:

classmyview->createobject();      //

物件直接呼叫用

cruntimeclass

本身的createobject()

現在,細心的朋友已經能清楚動態建立需要的步驟: 1

、定義乙個不帶引數的建構函式(預設建構函式);因為我們是用

createobject()

動態建立,它只有一條語句就是

return new ***

,不帶任何引數。所以我們要有乙個無參建構函式。 2

、類說明中使用

declare_dyncreate

(classnmae

)巨集;和在類的實現檔案中使用

implement_dyncreate

(classname

,baseclass

)巨集;這個巨集完成構造

cruntimeclass

物件,並加入到鍊錶中。 3

、使用時先通過巨集

runtime_class

得到類的

runtime

資訊,然後使用

cruntimeclass

的成員函式

createobject

建立乙個該類的例項。 4

、cobject* pobject = pruntimeclass->createobject();//

完成動態建立。

摘自:http://blog.csdn.net/liyi268/archive/2005/03/04/310895.aspx

追根究底,MFC六大關鍵技術剖析(三)

三 動態建立 動態建立就是執行時建立指定類的物件,在mfc中大量使用。如框架視窗物件 視物件,還有文件物件都需要由文件模板類物件來動態的建立。我覺得這是每個mfc的學習者很希望理解的問題。初次接觸mfc的時候,很容易有這樣的迷惘。mfc的幾大類不用我們設計也就罷了,但最疑惑的是不用我們例項化物件。本...

追根究底,MFC六大關鍵技術之剖析(二)

追根究底,mfc六大關鍵技術之剖析 二 二 執行時型別識別 rtti 執行時型別識別 rtti 即是程式執行過程中知道某個物件屬於某個類,我們平時用c 程式設計接觸的rtti一般是編譯器的rtti,即是在新版本的vc 編譯器裡面選用 使能rtti 然後載入typeinfo.h檔案,就可以使用乙個叫t...

追根究底,MFC六大關鍵技術之剖析(2)

追根究底,mfc六大關鍵技術之剖析 第二部分 小李先生 二 執行時型別識別 rtti 執行時型別識別 rtti 即是程式執行過程中知道某個物件屬於某個類,我們平時用c 程式設計接觸的rtti一般是編譯器的rtti,即是在新版本的vc 編譯器裡面選用 使能rtti 然後載入typeinfo.h檔案,就...