C++實現 反射 機制( 即根據 類名 建立 類例項)Create C++ Object Dynamically
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語句了。