/*********************************************************************************************************************
*   发布日期: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. Echart实现多个y轴,坐标轴的个数及名称由后台传过来的json数据决定。

    yAxis: function(){ var yAxis=[]; for(var i=0;i<legend1.length;i++){ var item={ name:legend1[i], t ...

  2. 同一台主机部署两个比特币钱包以及rpc服务的摘要

    .bitcoin QA Test环境 启动指定参数: "C:\Program Files (x86)\Bitcoin\bitcoin-qt.exe" -testnet -serve ...

  3. Win7自带功能,刻录光盘遇到的问题

    Win7系统的可以使用系统自带有光盘刻录功能来刻录光盘. 把一张空白光盘放入刻录机,打开“计算机”窗口,双击刻录机图标,弹出“刻录光盘”对话框,选择刻录类型.这里有两个选项:一个是“类似于USB闪存驱 ...

  4. PAT 1001 害死人不偿命的(3n+1)猜想 (15)(C++&JAVA&Python)

    1001 害死人不偿命的(3n+1)猜想 (15)(15 分) 卡拉兹(Callatz)猜想: 对任何一个自然数n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把(3n+1)砍掉一半.这样一直反 ...

  5. Thrift.0

    0. Thrift的特性 1. 安装Thrift编译器 [Todo] http://thrift.apache.org/docs/install/ http://thrift.apache.org/d ...

  6. 使用hMailServer搭建邮件服务器

    本文没有什么高深的技术内容,只是使用hMailServer,介绍搭建邮件服务器的全过程,供参考. 一.安装邮件服务器组件 打开软件,点下一步 选择存储数据的数据库,这里有两种选择, 一种是使用嵌入型数 ...

  7. Minimum Window Substring LT76

    Given a string S and a string T, find the minimum window in S which will contain all the characters ...

  8. Linux修改/etc/profile配置错误command is not found自救方法

    export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin

  9. IOS初级:UITableView

    先来看一下tableview 的结构(plain style). --------------------------------------       + header               ...

  10. windows + php7.1 + redis3.1.4

    首先确定PHP版本(MSVC14 x64 NTS) 下载redis扩展 拷贝php ext目录,修改php.ini配置,添加 extension=php_redis.dll 重启apache,确认re ...