/*********************************************************************************************************************
*   发布日期: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》系列之动态创建的更多相关文章

  1. MFC CStatic类动态创建

    如果我使用下面风格: m_PictureCtrl.Create(NULL, WS_EX_TRANSPARENT|WS_CHILD|WS_VISIBLE|WS_TABSTOP|SS_OWNERDRAW, ...

  2. MFC 对话框中动态创建N级菜单以及响应事件

    创建一个基于对话框的工程,工程名为CreateMenu 为该对话框增加一个文件菜单项和测试菜单项,如下图所示   测试菜单项至少要有一个子菜单项 在对话框属性中关联该菜单 在resource.h中增加 ...

  3. 【MFC】VS2013 动态创建快捷菜单(右键菜单)

    参考 http://blog.csdn.net/csdnzhwk/article/details/47395639 参考 http://blog.csdn.net/jiadabin/article/d ...

  4. 【转载】MFC动态创建控件及其消息响应函数

    原文:http://blog.sina.com.cn/s/blog_4a08244901014ok1.html 这几天专门调研了一下MFC中如何动态创建控件及其消息响应函数. 参考帖子如下: (1)h ...

  5. MFC动态创建控件及其消息响应函数

    这几天专门调研了一下MFC中如何动态创建控件及其消息响应函数. 参考帖子如下: (1)http://topic.csdn.net/u/20101204/13/5f1b1e70-2f1c-4205-ba ...

  6. 《深入浅出MFC》– Document-View深入探讨

    1.其实Document/View不是什么新东西,Xerox PARC实验室是这种观念的滥觞.它是Smalltalk环境中的关键性部分,在那里它被称为Model-View-Controller(MVC ...

  7. 《Entity Framework 6 Recipes》中文翻译系列 (38) ------ 第七章 使用对象服务之动态创建连接字符串和从数据库读取模型

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第七章 使用对象服务 本章篇幅适中,对真实应用中的常见问题提供了切实可行的解决方案. ...

  8. 深入浅出Mybatis系列(九)---强大的动态SQL

    上篇文章<深入浅出Mybatis系列(八)---mapper映射文件配置之select.resultMap>简单介绍了mybatis的查询,至此,CRUD都已讲完.本文将介绍mybatis ...

  9. MFC之动态创建按钮

    打开VS 创建MFC基于对话框的工程,在对话框初始化方法中动态创建一个按钮实例: 1> CButton *pMyButton = new CButton();CEdit *pMyEdit = n ...

随机推荐

  1. 小程序 picker 多列选择器 数据动态获取

    需求是将各校区对应各班级的数据 以两列选择器的方式展示出来,并且可以在选择完成之后记录选结果参数. 校区数据 和 班级数据 分别是两个接口,以 校区 teach_area_id 字段关联 其各班级数据 ...

  2. select into tb_temp2 from tb_temp1 创建临时表实现上一个、下一个功能,使用完毕就删除临时表

    好久没有写过Sql了,今天遇到一个问题,业务逻辑是: 一个商品可以属于多个分类,在显示商品详情的时候,要求可以点击“上一个”,“下一个” 查看和该商品在同一个分类下的其他商品,商品具有排序号. 这样我 ...

  3. Django 导入css文件,样式不起作用。Resource interpreted as Stylesheet but transferred with MIME type application/x-css

    笔者今天在模板中加载css文件时,发现 css样式能够下载再来却无法起作用,而且,图片.js都能够正常使用. 并且 浏览器提示: Resource interpreted as Stylesheet ...

  4. 11.Mysql视图

    11.视图11.1 什么是视图 视图view是一张虚拟表,它不存储数据,数据仍在表里,视图由一条查询表的select语句创建,视图只存储select语句. 可以将复杂的查询语句封装成视图,用户可以从视 ...

  5. andorid 配置器组件和提示消息

    .xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android ...

  6. Lftp 简单使用步骤

    有一用户需要在Linux上面将数据备份至存储上面,但是不支持挂载. 只可以FTP. 找了下,Lftp 这款FTP Client 满足用户的需求. 相关资料参考:http://blog.chinauni ...

  7. NOIP需要掌握的内容(大致

    1.排序算法(快排.选择.冒泡.堆排序.二叉排序树.桶排序)2.DFS/BFS 剪枝 哈希表3.树   ①遍历   ②二叉树   ③二叉排序树(查找.生成.删除)   ④堆(二叉堆.左偏树.堆排序)  ...

  8. 基于centos6.5 hadoop 伪分布式安装

    步骤1:修改IP 地址和主机名: vi /etc/sysconfig/network-scripts/ifcfg-eth0 如果该文件打开为空白文件代表你计算机上的网卡文件不是这个名称“ifcfg-e ...

  9. activiti如何获取当前节点以及下一步路径或节点(转)

    ACTIVITI相对于JBPM来说,比较年轻,用的人少,中文方面的资料更少,我根据网上到处找得资料以及看官方文档总结出来了代码,非常不容易啊.废话不多说,直接上代码吧: 首先是根据流程ID获取当前任务 ...

  10. css过渡动画

    具体代码:1.水平翻转-moz-transform:scale(-1,1);-webkit-transform:scale(-1,1);-o-transform:scale(-1,1);transfo ...