动态类(类工厂)总结
一、动态类的作用
动态类应用的一个类似的例子便是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;
}