《深入浅出MFC》系列之动态创建
/*********************************************************************************************************************
* 发布日期:2017-11-13 16:23:44
* 进度:
* 作者:LuoTian
* 备注:动态创建
*********************************************************************************************************************/
这一篇承接上一篇的运行时类型识别,当各个类像链表一样串接之后,做各种功能就比较简单。
动态创建的思路:
动态创建就是指输入一个类名就能创建一个对象,比如在控制台中输入Base,就能创建Base类的对象。
假设有三个类Base,B,C,继承关系为Base<-B<-C,其中Base为根类。根据上一篇所写,将这三个类通过CRuntimeClass进行串接。因为动态创建需要这个,原因容易理解,假如你输入一个Base,程序则必须根据输入的这个字符串在链接的类中查找是否存在Base这个类,于是就需要遍历,从C开始一直查找到Base。
为了实现这些功能,除了在CRuntimeClass里面再添加一些信息之外,还在能动态创建的类中添加一个静态函数CreateObject( );
流程如下:
假定输入Base,程序根据pFirst从尾端开始遍历各个类,查找是否有类名=Base的类,如果不存在则程序返回。如果存在,再看它的一个字段m_pfnCreateObject是否为空,而这个m_pfnCreateObject是一个函数指针,所指向的就是在能动态创建的类中添加的静态函数CreateObject(),假如一个类不能动态创建,那么肯定没有这个CreateObject函数,则在初始化CRuntimeClass的时候,m_pfnCreateObject也就为NULL了,如果能动态创建,m_pfnCreateObject就指向了CreateObject( ),然后通过m_pfnCreateObject指针执行函数调用。
思路总结:
一、能动态创建的类中有CreateObject()函数。
二、能动态创建的类的CRuntimeClass结构中的m_pfnCreateObject字段初赋值为CreateObjec,如果为NULL,则不具备动态创建的能力。
//实现比较简单,直接new一个对象返回;
static Base * PASCAL CreateObject(){return new B;}
示例代码如下:
#include <iostream>
using namespace std;
#define PASCAL _stdcall
class Base; /***************核心的CRuntimeClass结构********************/
struct CRuntimeClass
{
char * name; //类名
int ClassSize; //类大小;
Base *(PASCAL * m_pfnCreateObject)();
CRuntimeClass *pBase;//基类的CRuntimeClass地址 Base * CreateObject();
static CRuntimeClass * PASCAL Load();
static CRuntimeClass *pFirst;
CRuntimeClass *pNext;
};
CRuntimeClass * CRuntimeClass::pFirst=NULL;//pFirst初始化为空; CRuntimeClass* PASCAL CRuntimeClass::Load()
{
char szClassName[];
CRuntimeClass* pClass;
cout << "输入需要动态创建的类名:";
cin >> szClassName; //在各个类的CRuntimeClass结构中查找是否存在输入的类名
for (pClass = pFirst; pClass != NULL; pClass = pClass->pNext)
{
if (strcmp(szClassName, pClass->name) == )
return pClass;
}
cout<<"没有找到该类名,程序退出!!"<<endl;
return NULL;
}
Base * CRuntimeClass::CreateObject()
{ if (m_pfnCreateObject == NULL)
{
cout<<"不能动态创建!!"<<endl;
return NULL;
}
else
{
Base * pObject =(*m_pfnCreateObject)();
return pObject;
}
}
//****************结束*****************************************/ struct AFX_CLASSINIT
{
AFX_CLASSINIT(CRuntimeClass *pNewClass)
{
pNewClass->pNext=CRuntimeClass::pFirst;
CRuntimeClass::pFirst=pNewClass;
}
}; class Base //根基类;
{
public:
static CRuntimeClass classBase;
virtual CRuntimeClass * GetRuntimeClass()const
{
return &Base::classBase;
}
virtual void SayHello()
{
cout<<"基类Base的SayHello"<<endl;
}
}; class B:public Base //B类
{
public:
static CRuntimeClass classB;
static Base * PASCAL CreateObject(){return new B;}
virtual CRuntimeClass * GetRuntimeClass()const{
return &B::classB;
}
virtual void SayHello(){ cout<<"类B的SayHello,动态创建对象成功!!"<<endl;}
}; class C:public B //C类
{
public:
static CRuntimeClass classC;
virtual CRuntimeClass * GetRuntimeClass()const{
return &C::classC;
}
}; //***********************实现部分*************************// struct CRuntimeClass Base::classBase={"Base",sizeof(Base),NULL,NULL};
static AFX_CLASSINIT _init_A(&Base::classBase);//② struct CRuntimeClass B::classB={"B",sizeof(B),B::CreateObject,&Base::classBase,};
static AFX_CLASSINIT _init_B(&B::classB);//③ struct CRuntimeClass C::classC={"C",sizeof(C),NULL,&B::classB,};
static AFX_CLASSINIT _init_C(&C::classC);//④ int main(int argc,char *argv[])
{
CRuntimeClass * pClassRef;
Base *pOb;
cout<<"共有三个类Base,B,C,其中B类具有动态创建能力... ."<<endl;
while(true)
{
if((pClassRef=CRuntimeClass::Load())==NULL)
break;
pOb=pClassRef->CreateObject();
if(pOb!=NULL)
pOb->SayHello();
}
return ;
}
《深入浅出MFC》系列之动态创建的更多相关文章
- MFC CStatic类动态创建
如果我使用下面风格: m_PictureCtrl.Create(NULL, WS_EX_TRANSPARENT|WS_CHILD|WS_VISIBLE|WS_TABSTOP|SS_OWNERDRAW, ...
- MFC 对话框中动态创建N级菜单以及响应事件
创建一个基于对话框的工程,工程名为CreateMenu 为该对话框增加一个文件菜单项和测试菜单项,如下图所示 测试菜单项至少要有一个子菜单项 在对话框属性中关联该菜单 在resource.h中增加 ...
- 【MFC】VS2013 动态创建快捷菜单(右键菜单)
参考 http://blog.csdn.net/csdnzhwk/article/details/47395639 参考 http://blog.csdn.net/jiadabin/article/d ...
- 【转载】MFC动态创建控件及其消息响应函数
原文:http://blog.sina.com.cn/s/blog_4a08244901014ok1.html 这几天专门调研了一下MFC中如何动态创建控件及其消息响应函数. 参考帖子如下: (1)h ...
- MFC动态创建控件及其消息响应函数
这几天专门调研了一下MFC中如何动态创建控件及其消息响应函数. 参考帖子如下: (1)http://topic.csdn.net/u/20101204/13/5f1b1e70-2f1c-4205-ba ...
- 《深入浅出MFC》– Document-View深入探讨
1.其实Document/View不是什么新东西,Xerox PARC实验室是这种观念的滥觞.它是Smalltalk环境中的关键性部分,在那里它被称为Model-View-Controller(MVC ...
- 《Entity Framework 6 Recipes》中文翻译系列 (38) ------ 第七章 使用对象服务之动态创建连接字符串和从数据库读取模型
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第七章 使用对象服务 本章篇幅适中,对真实应用中的常见问题提供了切实可行的解决方案. ...
- 深入浅出Mybatis系列(九)---强大的动态SQL
上篇文章<深入浅出Mybatis系列(八)---mapper映射文件配置之select.resultMap>简单介绍了mybatis的查询,至此,CRUD都已讲完.本文将介绍mybatis ...
- MFC之动态创建按钮
打开VS 创建MFC基于对话框的工程,在对话框初始化方法中动态创建一个按钮实例: 1> CButton *pMyButton = new CButton();CEdit *pMyEdit = n ...
随机推荐
- win下apache的error.log和access.log文件过大
在httpd.conf中修改ErrorLog和CustomLog的配置 ErrorLog "|E:/apache2.2/bin/rotatelogs.exe E:/apache2.2/log ...
- mui 注意事项
1>一切内容都要包裹在mui-content中 顶部导航栏(.mui-bar-nav).底部工具条(.mui-bar-footer).底部选项卡(.mui-bar-tab)放在.mui-cont ...
- ubuntu 无法挂载U盘
问题描述: usb 1-1: device descriptor read/64,error 18usb 1-1: device descriptor read/64,error 18usb 1-1: ...
- 获取URL某个参数
/* 获取URL某个参数(可以是中文) * 返回:字符串 */ function getUrlParam(key) { // 获取参数 var url = window.location.search ...
- python 面向对象编程 之 析构方法
析构方法:当对象在内存中被释放的时候,自动触发执行 如果产生的对象仅仅只是用户级别的, 那么无需定义__del__,如果对象还会向操作系统发生系统调用, 即一个对象有用户级别与内核级两种资源, 比如打 ...
- poj 1321 (简单DFS) 棋盘问题
题目:http://poj.org/problem?id=1321 最近状态有点down, 练练手 #include<cstdio> using namespace std; ][]; ] ...
- 关于redis和memcached的一些想法
看了redis和memcached,想到自己前几年以前会把内存分配及调用和程序写在一起.确实是不合理的.这样的话,主进程就会越来越大,而且模块也不是完全独立.不能做到松耦合. 实质就是把内存的读写I/ ...
- Spring 属性注入(三)AbstractNestablePropertyAccessor
Spring 属性注入(三)AbstractNestablePropertyAccessor Spring 系列目录(https://www.cnblogs.com/binarylei/p/10117 ...
- java 23种设计模式学习。
一.3大类设计模式:创建型,结构型,行为型. a.5种创建型模式:工厂方法,抽象工厂,单例,建造者,原型. b.7种结构型模式:适配器,装饰器,代理,外观,桥接,组合,享元. c.11种行为型模式:策 ...
- linux 查看信息-服务器相关
查看系统内核 查看磁盘信息 查看CPU的信息 查看内存相关信息