`
tansitongba
  • 浏览: 503643 次
文章分类
社区版块
存档分类
最新评论

深入浅出MFC学习笔记:(第三章MFC六大关键技术之仿真:类型识别,动态创建) .

 
阅读更多

第三章MFC六大关键技术之仿真:类型识别

深入理解MFC的内部运行原理,是本次学习《深入浅出MFC》的主要目的。要模仿的六大技术包括:

1MFC程序的初始化过程。

2RTTIRuntimetypeidentification)运行时类型识别。

3Dynamiccreation动态创建

4Persistence永久保存

5:消息映射

6:消息传递。

RTTI(运行时类型识别)

IsKindOf能够侦测某个对象是否属于某种类。即判断某一对象所属的类是否是父类或当前类;

要达到动态类型识别的能力,必须在构建类继承体系时记录必要的信息,这被称为类型型录表。MFC以链表的方式建立了此表。

类型型录表的每个元素为CRuntimeClass类型,其定义为:

classCRuntimeClass

{

public:

LPCSTRm_lpszClassName;//对象所属类名

Intm_nObjectSize//对象大小

UINTm_wSchema;//模式号

CObject*(PASCAL*m_pfnCreateObject)();//构建函数抽象类为NULL

CRuntimeClass*pBaseClasss;//基类CRuntimeClass对象指针。

StaticCRuntimeClass*pFirstClass;//链表头指针。

CRuntimeClass*m_pNextClass;//下一指针。

};

MFC使用此类作为每个类的成员变量。使用宏定义为每个类定义了自己的CRuntimeClass成员变量。

DECLAR_DYNAMICIMPLENMENT_DYNAMIC

使用这两个宏将CRuntimeClass对象不知不觉放到类之中。

DECLARE_DYNMIC宏定义如下:

#defineDELCARE_DYNMIC(class_name)\

public:\

staticCRuntimeClassclass##class_name\

virtualCRuntimeClass*GetRuntimeClass()const;

##用来告诉编译器把两个字符串连接起来。

如果使用这个宏:DELCARE_DYNMICCView);

那么预编译器将生成下列代码:
public:

staticCRuntimeClassclassCView;

virtualCRuntimeClass*GetRuntimeClass()const;

以上代码仅仅是在类中定义CRuntimeClass对象,并定义一个返回CRuntimeClass对象地址的函数。注意CRuntimeClassstatic的,也就是说同一种类继承体系的对象共享一个CRuntimeClass对象。

初始化对象的内容以及建立类型型录表需要使用IMPLEMENT_DYNMIC宏。

#defineIMPLEMENT_DYNMIC(class_name,base_class_name)\

_IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,0xFFFF,NULL);

_IMPLEMENT_RUNTIMECLASS又是一个宏,它定义如下:

#define_IMPLEMENT_RUNTIMECLASS(class_name,\

base_class_name,wSchema,pfnNew)\

staticchar_lpsz##class_name[]=#class_name;\

CRuntimeClassclass_name::class##class_name=\

{_lpsz##class_name,sizeof(class_name),\

wSchema,pfnNew,\

RUNTIME_CLASS(base_class_name),NULL\

};

staticAFX_CLASSINIT_init##class_name\

(&class_name::class##class_name);\

CRuntimeClass*class_name::GetRuntimeClass()const\

{\

return&class_name::class##classname;\

}

#defineRUNTIME_CLASS(class_name)\

(&class_name::class##class_name);

AFX_CLASSINIT是一个类,看着跟宏定义似的,这样做很容易让人迷惑。它用于将本节点连接到类型型录表,定义如下:

classAFX_CLASSINIT

{

public:

AFX_CLASSINIT(CRuntimeClass*pNewClass)//构造函数

{

pNewClass->m_pNextClass=CRuntime::pFirstClass;

CRuntimeClass::pFirstClass=pNewClass;

}

};

用法:

classCWnd:publicCCmdTarget

{

public:

DECLARE_DYNAMIC(CWnd);

};

IMPLEMENT_DYNMIC(CWnd,CCmdTarget);

代码展开后为;

classCWnd:publicCCmdTarget

{

public:

staticCRuntimeClassclassCView;

virtualCRuntimeClass*GetRuntimeClass()const

};

staticchar_lpszCWnd[]="CWnd";

CRuntimeClassCWnd::classCWnd=

{

_lpszCView,sizeof(CWnd),FFFF,NULL,&Wnd::classCWnd,NULL);

};

staticAFX_CLASSINIT_init_CWnd(&CWnd::classCWnd);

{

Return&CWnd::classCWnd;

}

定义宏的过程很复杂,但是一旦定义好之后,在使用时仅仅两句话就可以完成定义CRuntimeClass对象并且连接类型型录链表的工作。

CObject是所有类的基类,也是链表的头,此类应特别定义,不能在CObject内使用定义好的宏。

classCObject

{

public:

virtualCRuntimeClass*GetRuntimeClass()const;

staticCRuntimeClassclassCObject;

};

staticcharszCobject[]="CObject";

structCRuntimeClassCObject::classCObject=

{

szCObject,sizeof(CObject),0xFFFFNULLNULL,NULL

};

staticAFX_CLASSINIT_init_CObject(&Cobject::classObject);

CRuntimeClass*CObject::GetRuntimeClass()const

{

return&CObject::classCObject;

}

由于CRuntimeClass对象是static成员变量,因此需要在类外初始化。如果忘记初始化将会报链接错误。

CRuntimeClass*CRuntimeClass::pFirstClass=NULL;

建好了类类型路表,要实现IsKindOf功能很容易。首先在CObject加上一个IsKindOf函数,于是所有继承自此类的类都具有类型识别的功能。能够将某个CRuntimeClass对象与类类型型录中的元素进行比较。如:

classCObject

{

public:

boolIsKindOf(constCRuntimeClass*pClass)const

{

CRuntimeClass*pClassThis=GetRuntimeClass();

while(pClassThis)

{

if(pClassThis==pClass)

returntrue;

pClassThis=pClassThis->m_pBaseClass;//沿着基类寻找。

}

returnfalse;

}

}

如果我们调用CWnd*cw=newCWnd;

cw->IsKindOf(RUNTIME_CLASS(CFrameWnd));

RUNTIME_CLASS实际就是&CFrameWnd::classCFrameWnd,它就是CFrameWndstaticCRuntimeClass类型成员。函数内利用GetRuntimeClass取得本类的CRuntimeClass对象的地址,即&CWnd::classCWnd,然后进行比较。因为每一类型共用一个staticCRuntimeClass对象,因此属于同于类的CRuntimeClass对象的地址相同。

动态创建

每一类的构建函数可以记录在类型别录中,当获得一个类名称,通过查找类别型录表找出对应的元素,然后调用其构建函数产生新对象。

CRuntimeClassm_pfnCreateObject即为构建函数首地址。

为了实现动态创建,需要添加两个宏:

DECLARE_DYNCREATEIMPLEMENT_DYNCREATE

如:

#defineDECLARE_DYNCREATE(class_name)\

DECLARE_DYNCREATE(class_name)\

staticCObject*PASCALCreateObject();

#defineIMPLEMENT_DYNCREATE(class_name,base_class_name)\

CObject*PASCALclass_name::CreateObject()\

{returnnewclassname;};\

_IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,

0xFFFF,class_name::CreateObject)

CFrameWnd为例,下列程序代码:

classCFrameWnd:publicCWnd

{

public:

DECLEARE_DYNCREATE(CFrameWnd);

};

IMPLEMENT_DYNCREATE(CFrameWnd,CWnd);

展开如下:

classCFrame:publicCWnd

{

public:

staticCRuntimeClassclassCFrameWnd;

virtualCRuntimeClass*GetRuntimeClass()const;

staticCObject*PASCALCreateObject();

};

CObject_PASCALCFrameWnd::CreateObject()

{

returnnewCFrameWnd;
}

staticchar_lpszCFrameWnd[]="CFrameWnd";

CRuntimeClassCFrameClass::classCFrameWnd={

_lpszCFrameWnd,sizeof(CFrameWnd),0xFFFF,CFrameWnd::CreateObject,RUNTIME_CALSS(CWnd),NULL};

staticAFX_CLASSINIT_init_CFrameWnd

(&CFrameWnd::classCFrameWnd);

CRuntimeClass*CFrameWnd::GetRunimeClass()const

{return&CFrameWnd::classCFrameWnd;}

注意对象构建函数为static函数。

为了支持动态创建需要在CRuntimeClass内添加两个函数:CreateObjectCRuntimeClass::Load成员函数。

CObject*CRuntimeClass::CreateObject()

{

If(m_pfnCreateObject==NULL)//不支持动态创建。

{

throwruntime_error("此类不支持动态创建");

ReturnNULL;

}

CObject*pObject=(*m_pfnCreateObject)();

ReturnpObject;

}

CRuntimeClass*PASCLCRuntimeClass::Load()

{

CharszClassName[64];

CRuntimeClass*pClass

cout<<"输入一个类名:";

cin>>szClassName;

for(pClass=pFirstClass;pClass;pClass=pClass->m_pNextClass)

{

if(strcmp(szClassName,pClass->m_lpszClassName)==0)

returnpClass;

returnNULL;

}

}

以下为类型识别及动态创建的完整代码:





分享到:
评论

相关推荐

    深入浅出MFC读书笔记3

    深入浅出MFC读书笔记3 在MFC中,Document-View架构是一个非常重要的概念。本文将对Document-View架构中的关键组件进行深入探讨,并对其实现思路进行详细的解析。 首先,让我们来看一下Document的概念。在MFC中,...

    《深入浅出MFC》第三章MFC关键技术仿真 vs2013代码

    总之,《深入浅出MFC》第三章的内容涵盖了MFC的核心概念和技术,是Windows开发人员理解和掌握MFC编程的宝贵资源。通过学习这一章,开发者可以构建功能丰富的Windows应用程序,并对MFC有深入的理解。

    深入浅出.MFC.pdf深入浅出.MFC.pdf4

    深入浅出.MFC.pdf深入浅出.MFC.pdf深入浅出.MFC.pdf

    《深入浅出MFC》高清第二版(书签)_深入浅出MFC_c++mfc_

    《深入浅出MFC》是一本专为C++程序员深入理解Microsoft Foundation Classes (MFC) 库而编写的经典教程。MFC是微软提供的一套C++类库,用于简化Windows应用程序开发,它将Windows API封装成易于使用的C++类。这本书的...

    深入浅出MFC读书笔记2

    深入浅出MFC读书笔记2是对MFC框架的进一步学习和理解,主要涵盖了MFC的基础概念、类库结构以及程序构建的关键要素。MFC(Microsoft Foundation Classes)是微软为Windows平台开发的应用程序提供的一种类库,它基于...

    MFC 深入浅出 + 学习笔记

    文件`深入浅出MFC笔记(配合原书的好笔记).doc`可能是作者阅读侯捷的《深入浅出MFC》后所做的详细笔记,可能包含了对书中关键概念的理解、例子的解析以及个人的实践心得。这种学习方式对于巩固理论知识和提高实际编程...

    深入浅出.MFC.pdf深入浅出.MFC.pdf2

    深入浅出.MFC.pdf深入浅出.MFC.pdf深入浅出.MFC.pdf

    深入浅出MFC 深入浅出MFC 深入浅出MFC

    《深入浅出MFC》是一本专注于Microsoft Foundation Classes (MFC) 的技术书籍,MFC是微软为Windows应用程序开发提供的一套C++类库。它将Windows API进行了封装,使得开发者能够更方便地构建Windows桌面应用程序。MFC...

    MFC入门教程:1天深入浅出MFC

    MFC入门教程:1天深入浅出MFC

    《深入浅出MFC》读书心得

    MFC 是 Windows 程序设计的基础,深入浅出 MFC 是学习 Windows 程序设计的不二之选。 《深入浅出MFC》读书心得涵盖了 Windows 程序设计的方方面面,包括程序结构、头文件、makefile、消息循环等知识点,为开发者...

    深入浅出 MFC (第二版) 高清晰

    第三章 MFC六大关键技术之仿真 第二篇 欲善工事先利其器 第四章 Visual C++ 集成开发环境 第三篇 浅出MFC程序设计 第五章 总观Application Framework 第六章 MFC程序的生死因果 第七章 简单而完整:MFC骨干程序 第四...

    深入浅出MFC.pdf

    《深入浅出MFC》是一本专注于Microsoft Foundation Classes (MFC) 的技术书籍,MFC 是微软为Windows应用程序开发提供的一套C++类库。它将Windows API进行了封装,使得开发者能够更方便地构建基于Windows操作系统的...

    深入浅出.MFC.pdf深入浅出.MFC.pdf3

    深入浅出.MFC.pdf深入浅出.MFC.pdf深入浅出.MFC.pdf

    深入浅出.MFC.pdf深入浅出.MFC.pdf5

    深入浅出.MFC.pdf深入浅出.MFC.pdf深入浅出.MFC.pdf

    深入浅出MFC简体中文版(附源码

    《深入浅出MFC简体中文版》是一本专注于Microsoft Foundation Classes (MFC) 的技术专著,旨在帮助读者深入理解和应用这一强大的Windows应用程序开发框架。MFC是微软为C++开发者提供的一种库,它封装了Windows API,...

    深入浅出mfc光盘

    该压缩包包含了《深入浅出MFC》第二版的配套源代码,可供读者在学习过程中实践和探索。 MFC本身是微软为了简化Windows API编程而设计的,它封装了Windows API,使得开发者可以通过面向对象的方式编写Windows应用...

Global site tag (gtag.js) - Google Analytics