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