探察RUNTIME CLASS之類的秘密

2021-05-22 22:05:08 字數 3198 閱讀 4609

探察runtime_class之類的秘密

我們學mfc學到 文件,檢視和框架 的時候,知道必須在這三個類的派生類的類宣告裡加上declare_dyncreate,然後在類宣告外合適的地方加上 implement_dyncreate ,然後 文件,檢視和框架,還有 文件模板 就可以協調工作了。檢視msdn,發現類似的巨集有這幾對:

declare_dynamic 和 implement_dynamic

declare_dyncreate 和 implement_dyncreate

declare_serial 和 implement_serial

1。 runtime_class 巨集的定義是這樣的:

#define runtime_class(class_name)

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

其中##的意思是把##兩邊的符號都進行巨集擴充套件(如果它們是巨集的話),然後把擴充套件後的內容連線在一起,中間不加空格。例如:runtime_class(cview)將被擴充套件成:

(cruntimeclass*)(&cview::classcview)

但這個classcview是什麼意思?原來,classcview是由declare_dynamic(cview)引入的乙個public屬性的cruntimeclass型別的靜態成員變數:

static const afx_data cruntimeclass classcview;

原來runtime_class的作用就是引用由declare_dynamic巨集引入的靜態成員變數。

2。declare_dynamic(class_name)

由於篇幅的原因,巨集的具體定義**就不列出來了,感興趣的可以去看檔案

afx.h。

該巨集往類中宣告了三個成員:

protected:

static cruntimeclass* pascal _getbaseclass();

public:

virtual cruntimeclass* getruntimeclass() const;

static const afx_data cruntimeclass class##class_name;

有兩個成員函式,乙個靜態成員變數 class+類名 , 同runtime_class相似,如果是declare_dynamic(cview)的話,這個靜態成員變數的名字將是classcview。可見這個成員變數的名稱是和declare_dynamic的引數有關的。在下文我們把這個成員變數統統記做class##class_name。

這個靜態成員和兩個成員函式在**被初始化和具體實現呢?原來是在implement_dynamic巨集裡。

3。implement_dynamic(class_name, base_class_name)

檢視它的巨集定義,如果_afxdll被定義了的話,由declare_dynamic引入的成員的初始化和實現是這樣的:

cruntimeclass* pascal class_name::_getbaseclass()

cruntimeclass* class_name::getruntimeclass() const

afx_comdat const afx_datadef

cruntimeclass class_name::class##class_name =

;//這是在初始化靜態成員變數class##class_name。

//cruntimeclass結構的各個成員的意義可檢視msdn。

4。_declare_dynamic(class_name)

該巨集的定義和declare_dynamic(class_name)基本一樣。不同之處是靜態成員class##class_name前面沒有const修飾符。

5。declare_dyncreate(class_name)

該巨集也往類中引入了declare_dynamic巨集所引入的那三個成員。除此之外,它還另外引入了乙個成員:

static cobject* pascal createobject();

該巨集引入的成員在implement_dyncreate裡初始化和實現。

6。implement_dyncreate(class_name, base_class_name)

該巨集自然是初始化和實現由declare_dyncreate引入的成員了。

我們看看createobject的實現:

cobject* pascal class_name::createobject()

呵,這個函式是如此簡單,它就是用cobject類裡過載的new操作符建立乙個該類型別的物件。

7。_declare_dyncreate(class_name)

該巨集引入了和declare_dyncreate引入的四個成員差不多的成員。唯一的區別是該巨集引入的靜態成員class##class_name前面沒有const修飾符。

8。declare_serial(class_name)

該巨集引入了和_declare_dyncreate所引入的一樣的四個成員,另外它還多了這麼一句:

afx_api friend carchive& afxapi operator>>(carchive& ar, class_name* &pob);

原來是把過載操作符operator>>的函式當作該類的友元。於是在操作符函式operator>>中就可以訪問該類的成員了。

9。implement_serial(class_name, base_class_name, wschema)

該巨集初始化了成員變數:

cruntimeclass class_name::class##class_name=

;//在這裡,class##class_name前面是沒有const修飾符的。

該巨集還實現了下列函式:

cobject* pascal class_name::createobject()

cruntimeclass* class_name::getruntimeclass() const

carchive& afxapi operator>>

(carchive& ar, class_name* &pob)

該巨集還宣告了乙個函式原型:

afx_classinit _init_##class_name(runtime_class(class_name)); 

RUNTIME CLASS 執行時間類)

學mfc學到文件,檢視和框架的時候,知道必須在這三個類的派生類的類宣告 裡加上declare dyncreate,然後在類宣告外合適的地方加上implement dyncrea te,然後文件,檢視和框架,還有文件模板就可以協調工作了。檢視msdn,發現 類似的巨集有這幾對 declare dyna...

博學之,審問之,慎思之,明辨之,篤行之

禮記 中庸 十九章有云 博學之,審問之,慎思之,明辨之,篤行之。這說的是為學的幾個層次,或者說是幾個遞進的階段。博學之 意謂為學首先要廣泛的獵取,培養充沛而旺盛的好奇心。好奇心喪失了,為學的慾望隨之而消亡,博學遂為不可能之事。博 還意味著博大和寬容。惟有博大和寬容,才能相容幷包,使為學具有世界眼光和...

接觸之,熟悉之,打破之

接觸之,熟悉之,打破之 拿破崙小時候就是孩子王,不管同夥伴們玩什麼遊戲,它總是贏家。同時,它更善於改變遊戲規則,以便能夠發揮他自己的優勢。如果能夠成為遊戲規則的左右者,那麼,在當今商戰中必定是最大的贏家。我們處在乙個有著各種各樣遊戲規則的大環境中,每時每刻都要面對不同的遊戲規則,轉換不同的角色,讓自...