探察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...
博學之,審問之,慎思之,明辨之,篤行之
禮記 中庸 十九章有云 博學之,審問之,慎思之,明辨之,篤行之。這說的是為學的幾個層次,或者說是幾個遞進的階段。博學之 意謂為學首先要廣泛的獵取,培養充沛而旺盛的好奇心。好奇心喪失了,為學的慾望隨之而消亡,博學遂為不可能之事。博 還意味著博大和寬容。惟有博大和寬容,才能相容幷包,使為學具有世界眼光和...
接觸之,熟悉之,打破之
接觸之,熟悉之,打破之 拿破崙小時候就是孩子王,不管同夥伴們玩什麼遊戲,它總是贏家。同時,它更善於改變遊戲規則,以便能夠發揮他自己的優勢。如果能夠成為遊戲規則的左右者,那麼,在當今商戰中必定是最大的贏家。我們處在乙個有著各種各樣遊戲規則的大環境中,每時每刻都要面對不同的遊戲規則,轉換不同的角色,讓自...