动态类(类工厂)总结

动态类(类工厂)总结

一、动态类的作用

动态类应用的一个类似的例子便是MFC中CWnd类的Create方法,其第一个参数为Window Class的名字,这就允许用户通过class的名字来创建相应的窗口。C++不是动态语言,所以没法从语言机制上实现类的动态创建,但很明显这样的需求是存在的。

要想实现这一点,必须有一个“管理中心”,用于登记类的名字,并且通过名字能够调用某个方法来创建相应的类。结合类工厂的设计思想,这里我们让一套继承体系中的基类作为“管理中心”,由它来维护所有派生类的必要信息,包括类名和工厂函数,这二者必须建立起映射关系,map是不错的选择。

二、动态类原理

1、  基本原理

动态类就是给基类定义一个静态的map,如下例:

static map<const char*, ClassGen> class_set;

这样,没一个新建的类都可以被记录在这个map表中,而且也便于程序根据名称来调用响应的类。

其他的部分都是围绕着这个map运行的,都是对map进行增加、查找之类的操作。

使用宏定义,可以加快程序的响应速度。

动态类的实现,代码并不唯一,功能也不仅限于此。不过下面实现的简单的动态类会给我们很大的参考价值。

2、宏定义的小知识

代码中每个行末都有“\”这是要把行末的换行符号转译掉,避免他影响宏定义。“##”符号在宏定义中起到一个连接的作用,比如

#define FUN(var) var##ing

最后FUN(str)的结果就是string。

在宏定义中“#”代表的取变量的值,比如

#define FUN(var) #var

string str = FUN(string);

str的值就是“string”,如果没有#,翻译之后的语句就是 string str = string这样会出现错误。

3、 源码分析

在动态类创建过程中,只需要使用以下四个语句:

DECLARE_DYNCRT_BASE(Base) // 声明动态基类
DECLARE_DYNCRT_CLASS(Derived, Base) // 声明动态类

IMPLEMENT_DYNCRT_BASE(Base) // 实现动态基类
IMPLEMENT_DYNCRT_CLASS(Derived) // 实现动态类
后面的两个实现,就是两个变量定义,主要说前面两个语句,在下面的代码中可以用一个语句概括:

base::Register(#derived, Create); \

这个语句在动态派生类中,意思就是调用动态基类的Register函数,第一个#derived是取动态派生类的类名,Create是调用动态派生类的自己的创建函数返回动态基类类型的一个指针,实际上这个指针式指向派生类的。

因为是宏定义的形式,所以在main函数运行之前,这些操作早就已经完成了。

另外,程序编译的过程如下:

C源程序头文件-->预编译处理(cpp)-->编译程序本身-->优化程序-->汇编程序-->链接程序-->可执行文件

三、动态类源码解析

#ifdef _MSC_VER
#pragma warning(disable: 4786)
#endif
#include <iostream>
#include <map>
using namespace std;

// 用于声明具有动态创建功能的基类 
#define DECLARE_DYNCRT_BASE(base) \
public: \
    typedef base* (*ClassGen)(); \
    static void Register(const char* class_name, ClassGen class_gen) \
    { \
        class_set.insert(map<const char*, ClassGen>::value_type(class_name, class_gen)); \
    } \
public: \
    static base* Create(const char* class_name) \
    { \
        map<const char*, ClassGen>::iterator iter; \
        if((iter = class_set.find(class_name)) != class_set.end()) \
        { \
            return ((*iter).second)(); \
        } \
        return NULL; \
    } \
protected: \
    static map<const char*, ClassGen> class_set; 

// 用于实现基类 
#define IMPLEMENT_DYNCRT_BASE(base) \
map<const char*, base::ClassGen> base::class_set;

// 用于声明一个能够被动态创建的类 
#define DECLARE_DYNCRT_CLASS(derived, base) \
public: \
    struct derived##Register \
    { \
        derived##Register() \
        { \
            static bool bRegistered = false; \
            if(!bRegistered) \
            { \
                base::Register(#derived, Create); \
                bRegistered = true; \
            } \
        } \
    }; \
    static base* Create() \
    { \
        return new derived; \
    }

// 用于实现一个能够被动态创建的类  
#define IMPLEMENT_DYNCRT_CLASS(derived) \
static derived::derived##Register derived##_for_registering; 

// 测试
class Base
{
    DECLARE_DYNCRT_BASE(Base) // 声明动态基类 
    DECLARE_DYNCRT_CLASS(Base, Base) // 基类自己也可以动态创建 
public:
    virtual void Print() 
    {
        cout << "This is Base" << endl;
    }
};

IMPLEMENT_DYNCRT_BASE(Base) // 实现动态基类 
IMPLEMENT_DYNCRT_CLASS(Base) // 实现动态类

class Derived : public Base
{
    DECLARE_DYNCRT_CLASS(Derived, Base) // 声明动态类 
public:
    virtual void Print() 
    {
        cout << "This is Derived" << endl;
    }
};

IMPLEMENT_DYNCRT_CLASS(Derived) // 实现动态类

int main()
{
    Base* pBase = Base::Create("Base"); // 类名可以动态输入
    if(pBase) pBase->Print(); // 创建成功调用虚函数
    else cout << "Create Base error" << endl;
    
    Base* pDerived = Base::Create("Derived"); // 类名可以动态输入
    if(pDerived) pDerived->Print(); // 创建成功调用虚函数
    else cout << "Create Derived error" << endl;
    
    system("pause");
    return 0;
}

  

转载于:https://www.cnblogs.com/bugutian/p/4490916.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值