《深入浅出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 ...
随机推荐
- Windows服务安装、卸载、启动和关闭的管理器
最近在重构公司的系统,把一些需要独立执行.并不需要人为关注的组件转换为Windows服务,Windows服务在使用的过程中有很多好处,相信这一点,就不用我多说了.但是每次都要建立Windows服务项目 ...
- BOM DOM jQuery
. BOM . location相关 . location.href . location.href="http://www.sogo.com" . location.reload ...
- C# oracle to_date 日期型 参数传值
C#操作oracle,date字段,使用参数传值 例子一,获取三小时前的记录 public static DataTable Query() { const string sSql = &qu ...
- 反射中,Class.forName 和 classloader 的区别
https://blog.csdn.net/qq_27093465/article/details/52262340 java中class.forName()和classLoader都可用来对类进行加 ...
- R语言读取Hive数据表
R通过RJDBC包连接Hive 目前Hive集群是可以通过跳板机来访问 HiveServer, 将Hive 中的批量数据读入R环境,并进行后续的模型和算法运算. 1. 登录跳板机后需要首先在Linux ...
- Qt样式表的使用
Qt中可以灵活的使用层叠样式表(CSS),其语法和CSS很相似.因为HTML CSS的灵活性,所以可以很方便的为QT界面设计自己需要的外观.除了子类化Style类,使用QT样式表(QStyleShee ...
- TCHAR函数查询
https://blog.csdn.net/is2120/article/details/27542927
- MySQL数据库相关操作
查看数据库 mysql> SHOW DATABASES; 选择数据库 mysql> USE 数据库名称: 查看当前数据库 mysql> select database(); -- 第 ...
- [SoapUI] 判断工程下某个文件是否存在,存在就删除
def excelName = "AllTests-Fails" String projectPath = context.expand( '${projectDir}' ) St ...
- js--延时消失的菜单--(笔记)
html:有4个li,li下分别有一个span <script> window.onload=function(){ var aLi=document.getElementsBy ...