/*********************************************************************************************************************
*   发布日期: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. ios简单国际化

    1.在PROJECT中Info得Localizations中添加语言 2.新建Localizable.strings(一定是这个文件名),在右侧属性栏的Localization中勾选出你需要的语言 3 ...

  2. mysql5.7 生成列 generated column

    生成列的值是根据列定义中的表达式计算得出的. mysql5.7支持两种类型的生成列: 1.virtual 生成列:当从表中读取记录时,才计算该列值.不会把数据持久化在硬盘上. 2.stored 生成列 ...

  3. EF语句拦截器-匹配当前的Controller,Action,User

    示例代码,ps:一切都能实现,关键是你尝试的方向,别把简单问题复杂化导致进入死胡同出不来. using Mobile360.Core.Interfaces; using Mobile360.Core. ...

  4. mysql导入慢解决方法

    [mysqldump]max_allowed_packet = 512M [mysqld] interactive_timeout = 120 innodb_change_buffering=alli ...

  5. input 原生上传文件(type = file)

    1.表单上传文件的步骤: - 1)设置enctype 默认为:enctype="application/x-www-form-urlencoded"(一般不设置) 若要表单中有需要 ...

  6. localstorage和vue结合使用2

    html <template> <div class="hello"> <div class="page-top"> < ...

  7. gcc编译器如何生成指定的文件名

    放哪里都可以,进到文件所放路径,用gcc编译器编译.如:gcc -o test test.c 就是说把test.c文件编译链接生成test可执行程序.在linux下生成test.out,然后再命令:. ...

  8. 计数器counter

    今天就讲了2个属性:1.计数器 2.列规则 列规则很简单:column-count:3; (列的具体个数) column-width:30px;(列宽)N个浏览器不兼容column-gap:10px; ...

  9. andorid 列表视图 ListView 之BaseAdapter

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

  10. BZOJ1935或洛谷2163 [SHOI2007]园丁的烦恼

    BZOJ原题链接 洛谷原题链接 很容易想到二维前缀和. 设\(S[i][j]\)表示矩阵\((0, 0)(i, j)\)内树木的棵数,则询问的矩形为\((x, y)(xx, yy)\)时,答案为\(S ...