深入浅出mfc学习笔记——六大关键技术之仿真_运行时和动态创建
1:PS88:MFC的类层次结构
<1>CObject
<2>CCmdTarget,CDocument
<3>CCmdTarget_CWinThread_CWinApp
CCmdTarget_CWnd_CView
CCmdTarget_CWnd_CFrameWnd
C++规定,全局对象的构建将比程序进入点更早。所以theApp的构造函数将更早与main。
2:RTTI(运行时类型识别)
编译时需选用/GR选项——包含typeinfo.h——使用新的typeid运算符,我希望我的类库具备iskindof的能力,能在执行期侦测某个对象时候属于某种类并传回 True或False。
要达到RTTI的能力。我们的类设计者一定要在类建构起来的时候。记录必要的信息。以建立型录,型录中的类信息。以链表的方式连接起来。方便一一比较。
以CRuntimeClass结构体描述之,其中至少需要类名称。链表的Next指针,以及链表的First指针。由于first 指针属于全局变量。所以它应该以static修饰。
struct CRuntimeClass
{
LPCSTR m_lpszClassName;
int m_nObjectsize
CRuntimeClass* m_pBaseClass;
Static CRuntimeClass* pFirstClass;
CRuntimeclass * m_pNextClass;
};
我希望每个类都能拥有这样一个CRuntimeClass成员变量。
为了能把CRuntimeClass对象赛到类之中,并声明一个可以抓到该对象地址的函数。我们定义Declare_dynamic宏。
出现在宏定义中的##说明将两个字符串串在一起。
为了各个CRunTimeClass对象的内容指定以及连接工作使用Implement_Dynamic宏来完成。
#define Implement_Dynamic(class name,base_class name)\_Implement_RuntimeClass(Class_name,base_class_name,0xffff,NULL)
//in .h
class Cview:public Cwnd
{
Declare_dynamic(CView)
}
//in implementation file
IMPlement_dynmaic(CView,Cwnd)
链表的头总是需要特别处理。所以我们的类根源CObject不能使用上面的宏。
Iskindof(类型识别)
为CObject加上一个iskindof 函数,于是此函数将被所有类继承它将把参数所指定的某个CRuntimeClass对象拿来与类别型录中的元素一一比较,比较成功(在型录中发现),就传回TRUE。否则传回False
3:Dynamic creation(动态创建)
如果我能够把类的大小记录在类别型录中。把建构函数(即将出现的CRuntimeClass::CreateObject)也记录在类别型录中。当程序在执行器获得一个类名称,它就可以在类别型录网中找出对应的元素,然后调用其建构函数,产生出对象。
类的对象记录在类别型录中。建构函数也记录在类别型录中。当程序在执行期间获得一个类名称,它就可以在类别型录网中找出对应的元素。然后调用其建构函数产生对象。
CRuntimeClass中多了CObject* CreateObject();
static CRuntimeClass *PASCAL load();
为了适应这新增的两个宏。添加新宏Declare_dyncreate和Implement_dyncreate,从宏的定义中我们可以看到有用动态创建能力的类库必然也拥有运行时类型识别能力,因为_dyncreate宏覆盖了_dynamic宏。
在.h中Declare_dyncreate(CFramewnd);在,cpp中implement_dyncreate(CWnd,CCmdTarget)
总结下:
当知道一个类名,去判断有没有这个类时,即进行类型识别,这时就是去找这个链表的过程。
当需要动态创建时,仅仅是在CRuntimeClasss结构体增加了根据类型new 类对象的函数,在定义类类型时,类中的CRuntimeClasss成员也进行了这个类对象的创建,并保存了对象指针。
下面是csdn中一个网友提供的解释。供为参考。
时可以在编译时确定的
一个类有一份自己函数的代码编译为二进制机器指令
如有 IMPLEMENT_DYNCREATE(A, baseA)
就是 return new A; 它是在编译时确定的
再有 IMPLEMENT_DYNCREATE(B, baseB)
就有另外一个确定的函数 return new B;
注意 不是
f(param)
{
return new(Patam)
}
现在的模板可以实现这一功能
template <class T>
T* new()
{
return new T;
}
以前的MFC是用宏来实现的 让编译器帮你写代码
if(p!=NULL)
{
AfxMessageBox( "!=NULL ");
ASSERT(p==NULL);
}
#include <iostream.h>
#define PASCAL _stdcall
class CObject;
#define IMPLEMENT_DYNCREATE(class_name,base_class_name)new class_name;
class CObject
{
public:
void f()
{
cout < < "I am here! " < < endl;
}
};
class CCmdTarget: public CObject
{
public:
static CObject* CreateObject();
};
int main()
{
CObject* pCObject = IMPLEMENT_DYNCREATE( CCmdTarget, CObject )
pCObject -> f();
return 0;
}
而dynamic creation,实际上是形成了一个链表。你只要知道类的名字,就能在链表中找到声称这个类的一个对象的方法(代码)。我做的点简化。
struct DynamicCreationList
{
char* className
char* pCodeToCreateAnObject;
DynamicCreationList* pNext;
}
这样你就能根据一个字符串(就是类的名字)来动态创建一个类的对象了。
声明了 DECLARE_DYNCREATE 后,一个类就强制性地在列表中加入了一项。
如果,用 new 来创建的话,很难实现动态。
你必须知道所有的类,然后用if ( inputClass == "class1 ")等等一大堆的判断才能实现动态创建。
1.类说明中使用DECLARE_DYNCREATE(CLASSNMAE)宏;和在类的实现文件中使用IMPLEMENT_DYNCREATE(CLASSNAME,BASECLASS)宏;这个宏完成构造CRuntimeClass对象,并加入到链表中。
2、使用时先通过宏RUNTIME_CLASS得到类的RunTime信息,当获得一个类名时,先用类别型录网判别这个类是否是链表中有的类,若是,就使用CRuntimeClass的成员函数CreateObject创建一个该类的实例。
3、CObject* pObject = pRuntimeClass->CreateObject();//完成动态创建
CRuntimeClass *pClassRef;
CObject* pOb;
while(1)
{
if((pClassRef=CRuntimeClass::load())==NULL)
break;
pOb= pClassRef->CreateObject();
if(pob!=NULL)
pob->SayHello();
}
http://www.pcdog.com/edu/vc/2005/12/g057056.html
http://hi.baidu.com/282535629/blog/item/6e59aec2defc2a3de5dd3bd5.html
http://www.ieing.cn/html-31903-1.html
http://hi.baidu.com/1005301774/blog/item/bd61b19173b7f887a877a445.html
转载于:https://www.cnblogs.com/lzjsky/archive/2010/06/18/1760035.html
深入浅出mfc学习笔记——六大关键技术之仿真_运行时和动态创建相关推荐
- 深入浅出MFC学习笔记
深入浅出MFC学习笔记 ithzhang CSDN博客:http://blog.csdn.net/ithzhang/article/category/1159054 转载于:https://blog. ...
- 学习MFC-----MFC六大关键技术
MFC六大关键技术 MFC六大关键技术之初始化过程 我并不认为MFC减轻了程序员们的负担,MFC出现的目的虽然似乎是为了让程序员不用懂得太多就可以进行视窗编程,但本人在MFC里徘徊了很久很久(因为那 ...
- 深入浅出MFC学习笔记:MFC六大关键技术仿真之RTTI运行时类型识别
RTTI(运行时类型识别) 参考文献:深入浅出MFC-侯捷 怎样去构造类别型录网? 一.定义数据结构: 其中pFirstClass指针属于痊愈变量,所以它应该以static修饰之. 而且我们最终希望达 ...
- 21、深入浅出MFC学习笔记,Application Framework简介
1.Application Framework是一个完整的程序模型:是一组合作无间的对象,彼此藉消息的流动而沟通,并且互相调用对方的函数以求完成任务.<?xml:namespace prefix ...
- 28、深入浅出MFC学习笔记,View功能的加强和重绘效率的提高
1.同一份Document的多个views,在Document的一个view改变了后,如何同步其它view呢? 让所有的Views 同步更新资料的关键在于两个函数: 1)CDocument::Upda ...
- 深入浅出MFC学习笔记(第6章 :MFC程序的生死因果)
第六章:MFC程序的生死因果 本章主要是从MFC程序代码中,找出一个windows程序原本该有的程序入口点.窗口类注册.窗口产生.消息循环.窗口函数等操作.抽丝剥茧彻底理解一个MFC程序的诞生与结束. ...
- LTE-5G学习笔记18--5G关键技术(想学更多快进群)
一.研究的背景及意义 自2009年5月27日瑞典电信运营商Telia宣布启用世界上第一个4G (LTE: Long Term Evolution)试商用网络以来,4G网络的部署已在全球全面开花.根据G ...
- LTE-5G学习笔记15--Volte关键技术TTI Bundling讲解
TTI:transmission time interval传输时间间隔,MAC层的概念,它说明了一个MAC传输块时间上的长度 在LTE中TTI=1ms TTI Bundling:TTI绑定,一般LT ...
- 深入浅出MFC学习笔记 消息
本章将会对MFC的消息映射和 命令传递机制做深入探讨. MFC规定了消息传递的路线,消息会按照这个路线传递下去,找不到归宿的话就交给DefWindowProc. 在产生窗口之前,如果我们在创建窗口时指 ...
最新文章
- 厦门大学宋宁宇:统计学专业到蚂蚁风控岗!
- sql左连接排序取第一个_详解kettle工具记录集连接功能及实验测试
- Winforn中怎样在窗体中打开另一个窗体
- echarts 环形图 默认高亮展示某个数据
- 关于Qt的事件循环以及QEventLoop的简单使用
- python os.path.splitext()的用法_Python常用模块之os.path
- 关于类的入门例子(1): 继承窗体
- 第九章 线程与内核对象的同步(4)
- 使用SSIS包将多个Excel文件中的数据导入SQL Server表中
- svn服务器搭建之备份3
- oe7 安装财务模块后,科目表没有导入成功
- MKVToolNix v7.4.0 正式版
- python 日期选择(包含时间选择)
- win10查询计算机显卡,windows10系统电脑查看显卡型号的两种方法
- 鸿蒙pc系统镜像,鸿蒙系统有pc版么_鸿蒙系统有pc版安装方法
- opencv(二)图像像素提取及操作
- eclipes 快捷键操作:
- 单片机编程学习:自己编写的一个很简单的传感器控制电机
- 第二次实验报告:使用Packet Tracer分析应用层协议
- Python 编程精选
热门文章
- 制作网站设计项目进度表让用户充分了解网站制作进程
- win32com python_python模块:win32com用法详解
- php视频录制插件,Chrome浏览器录屏扩展插件
- git 常用命令_git常用命令的使用
- apache shiro jar包_只需要6个步骤,springboot集成shiro,并完成登录
- ida android sign加密,最右sign-v2签名算法追踪及逆向还原
- 服务器cpu天梯图_九月手机处理器排名 2020年9月最新版手机CPU天梯图
- Android视图绘制逻辑与思想(一):attachToRoot到底有什么作用?
- 开发日记-20190527 关键词 ubuntu无线网卡驱动安装
- 圈复杂度本质上就是——分支覆盖率达到100%需要的测试用例数