My FAQ,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档 | 网通镜像
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > Visual C++ > 文档/视/框架
MFC抽象类之动态实现技术
作者:bigwhite20xx 时间:2001-10-08 10:08 出处:互联网 责编:MyFAQ
              摘要:MFC抽象类之动态实现技术

                         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<<"a obj is being created"<<endl;
}

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 CObject*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()--->CSingleDocTemplate::OpenDocumentFile()-->...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();
现在一切都很清晰了.

 

 

 

 

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 myfaq.com.cn All rights reserved. www.myfaq.com.cn 版权所有