Create C++ Object Dynamically
Introduction
C++不像C#和Java那样具有反射的能力,通常不能根据任意一个class name来创建该class的instance。但我们知道在MFC中,任何继承了CObject的类都可以根据其名字来创建实例,它是使用了一些宏。而我从来就不喜欢使用大把的宏,虽然有的时候宏可能比较方便,可能对某些人来说也更美观。
原理很简单——定义一个基类,维护一个其派生类信息(包括派生类的名字和创建实例的函数指针)的列表,而派生类在程序运行的最初始阶段就向基类注册其信息。
Design & Implementation
Base Class—— DynBase
Derived Class—— Any Class Derived from DynBase
DynBase
DynBase.h:
#pragma once #include <map> #include <string>
class DynBase; struct ClassInfo; bool Register(ClassInfo* ci); typedef DynBase* (*funCreateObject)();
//Assistant class to create object dynamicly struct ClassInfo { public: string Type; funCreateObject Fun; ClassInfo(string type, funCreateObject fun) { Type = type; Fun = fun; Register(this); } };
//The base class of dynamic created class. //If you want to create a instance of a class ,you must let //the class derive from the DynBase. class DynBase { public:
static bool Register(ClassInfo* classInfo);
static DynBase* CreateObject(string type);
private: static std::map<string,ClassInfo*> m_classInfoMap;
}; |
DynBase.cpp:
#include "stdafx.h" #include "DynBase.h"
std::map< string,ClassInfo*> DynBase::m_classInfoMap = std::map<string,ClassInfo*>();
bool DynBase::Register(ClassInfo* classInfo) { m_classInfoMap[classInfo->Type] = classInfo; return true; }
DynBase* DynBase::CreateObject(string type) { if ( m_classInfoMap[type] != NULL ) { return m_classInfoMap[type]->Fun(); } return NULL; }
bool Register(ClassInfo* ci) { return DynBase::Register(ci); } |
Derived Class
DerivedClass.h:
class DerivedClass : public DynBase { public:
virtual ~ DerivedClass ();
DerivedClass ();
static DynBase* CreateObject(){return new DerivedClass ();}
private:
static ClassInfo* m_cInfo; };
|
DerivedClass.cpp:
#include "stdafx.h" #include "DynBase.h" #include "DerivedClass.h"
DerivedClass::~ DerivedClass () { // ToDo: Add your specialized code here and/or call the base class }
DerivedClass:: DerivedClass () {
}
ClassInfo* DerivedClass::m_cInfo = new ClassInfo(“DerivedClass”,(funCreateObject)( DerivedClass::CreateObject));
|
How to Use
int _tmain(int argc, _TCHAR* argv[]) { DerivedClass * instance = (DerivedClass *)DynBase::CreateObject(“DerivedClass”); //do something system("pause"); return 0; } |
Postscript
C++虽然没有反射的功能也能在一定的情况下根据类名来动态创建其实例,虽然使用了全局静态函数以及静态成员这样不是很理想的方法——可也只能用这样的方法了。在我们使用工厂模式的时候,可以使用这样的方法来创建某产品的实例了,而不是使用大把的switch-case语句了。