MFC抽象類之動態實現技術 (轉)

worldblog發表於2007-12-12
MFC抽象類之動態實現技術 (轉)[@more@]

  MFC抽象類之動態實現技術
  前不久,我在北大和哈工大bbs上問了同 一個問題"抽象類能例項化麼 not sure",幾天後得到大蝦的解答,我自己又深入探討了一些,寫下這篇文章以讓和我有同樣問題的人能從苦惱中解脫出來.

  眾所周知,含有純虛或者建構函式被宣告為protected的類被稱之為抽象類
,初學者在教科書上一定得到以下結論:"切記:抽象類不允許例項化".但在實際中
有例外.
//in XX.h
class OBJ
{

  protected: OBJ();
  //something else
  friend OBJ*Createobj();//用static也行,mfc就用的是static
 
};

//in XX.cpp

OBJ::OBJ()
{cout<}

OBJ*Createobj()
{return new OBJ();}

//in test.cpp
void main()
{
 OBJ*ptr=Createobj();
 
 delete ptr;
 
}

run後結果如下:
a obj is being created
Press any key to continue

看來是例項成功了,當然這個例子離動態建立還有區別,下面讓我們看一看MFC是如何來進行動態建立的(不知你是否發現,在MFC的SDI和MDI中,都是用了動態建立機制,只是他使用了一些宏和CRuntimeClass這各類幫忙)

侯捷的"深入淺出MFC"中又很詳細的關於這方面的講解,不過他沒有提到實現這種做法的目的之一是抽象類例項化的實現.

其實現過程大致如下:MFC利用一些宏DECLARE_DYNCREATE,IMPLEMENT_DYNCREATE將一些主要的東西悄悄的插入到將具有動態生成的類中,我們以SDI的CMainFrame的動態生成為例,看一看CMainFrame的宣告,他的constuctor可是protected的呦,DECLARE_DYNCREATE在MainFrm.h中加了幾個重要的函式,其中對動態建立至關重要的是
  static C*PASCAL CreateObject();//他可是用來CMainFrame
  static const AFX_DATA CRuntimeClass classCMainFrame;  的constuctor
  看看他的實現:
  CObject*PASCAL CreateObject()
  { return new CMainFrame;}

但是我們在中好像看不到誰呼叫了這個函式,事實上微軟很秘密的 把他轉移給了CRuntimeClass結構
  看看CRuntimeClass結構
struct CRuntimeClass
{
// Attributes
 //somethingelse
 CObject* (PASCAL* m_pfnCreateObject)();
  //.....
// Operations
 CObject* CreateObject();
 
//...........

};
這裡我僅列出兩個與動態建立有關的成員.
IMPLEMENT_DYNCREATE宏完成了CMainFrame類中CRuntimeClass classCMainFrame的初始化工作,看下面程式碼
 #define IMPLEMENT_DYNCREATE(class_name, base_class_name)
 CObject* PASCAL class_name::CreateObject()
 { return new class_name; }
 IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF,
 class_name::CreateObject)

m_pfnCreateObject被賦值為CMainFrame::CreateObject,看出點門道了吧^_^.

再看看CObject* CRuntimeClass::CreateObject()的實現吧.

CObject* CRuntimeClass::CreateObject()
{
  .........
  return (*m_pfnCreateObject)();
}

也許你還是很糊塗,但不知道你了不瞭解SDI程式的啟動過程,它啟動時預設開啟一個單文件檔案,其呼叫順序如下:
CWinapp::OnFileNew()---&gtCSingleDocTemplate::OpenDocumentFile()--&gt...CDocTemplate::CreateNewFrame()
而CDocTemplate::CreateNewFrame()的實現如下:
 CDocTemplate::CreateNewFrame()
{//......
 CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject();
  //....
}
其中m_pFrameClass是指向CMainFrame成員CRuntimeClass classCMainFrame的指標,
下面從後到前捋清一下思路:
  m_pFrameClass->CreateObject()返回(*m_pfnCreateObject)(),而後者指向的是static CMainFrame::CObject*PASCAL CreateObject();
現在一切都很清晰了.

 

 

 

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-991763/,如需轉載,請註明出處,否則將追究法律責任。

相關文章