/********************************************\
|????歡迎轉載, 但請保留作者姓名和原文鏈接, 祝您進步并共勉!?????????? |
\********************************************/
標準C++ RTTI的仿MFC實現 - 只用2個宏來實現"根據對象名創建對象"
作者: Jerry Cat
時間: 2006/05/30
鏈接:?http://www.shnenglu.com/jerysun0818/archive/2006/05/30/7895.html
1. 起由:
C++ RTTI缺乏一些運行時信息即便是C++98這方面也不好使,無法根據對象名直接創建對象. 所以MFC為了實現序列化,從頭構造了自己的RTTI信息,并定義了一整套宏. 具體可以參考MFC源代中一下類和宏的實現:
CRuntimeClass, CObject, DECLARE_DYNAMIC, IMPLEMENT_DYNAMIC
2. 需求:
本人正在寫一個做集成測試的工具,有一個配置哪些case需要做測試的配置文件,類似結構如下:
<ut>
???? <case name="case1"/>
???? <case name="case2"/>
</ut>
因此當測試工具導入改配置信息時候,必須能夠根據 "case1", "case2"等名字創建相應的Case對象. 顯然C++沒有提供類似的功能.
3. 實現:
仿照MFC Serialize的實現,定義一個基類和2個宏. 需要被動態創建的對象從該基類派生,并將2個宏注冊到對象工廠(Factory對象),然后就
可以用該對象工廠根據對象名創建對象.
基類和宏的定義:
class CUTObject
{
public:
??? virtual ~CUTObject(){}
??? virtual void? SetUTName(CFString name);
??? virtual CFString GetUTName();
??? virtual CUTObject* Clone(){ return NULL; }
private:
??? CFString m_strUTName;
};
#define DECLARE_UTOBJECT(className) \
public: \
???????? virtual CUTObject* Clone() \
???????? { return new className(); }\
???????? static CUTObject* CreateObject() \
???????? { return new className(); } \
???????? static bool? RegisterObject(CFString utName) \
???????? { \
??????????? className *pObj = (className*)CreateObject(); \
??????????? CUTFactory *pFactory = CUTFactory::Instance(); \
??????????? pFactory->RegisterObject(utName, pObj); \
??????????? return true; \
????????? }
#define REGISTER_UTOBJECT(utName, className) bool b##className = className::RegisterObject(utName);
類工廠是一個標準的Singleton模式,提供2個方法 - RegisterObject和CreateObject:
class CUTFactory
{
public:
??? static CUTFactory* Instance();
private:
??? CUTFactory();
??? CUTFactory(const CUTFactory& other){}
??? CUTFactory& operator=(const CUTFactory& other){}
public:
??? bool? RegisterObject(CFString name, CUTObject *pObj);
??? CUTObject* CreateObject(CFString name);
private:
??? static CUTFactory* m_pInstance;
??? static std::map<CFString, CUTObject*> m_mapObjects;
};
4. 小結:
最關鍵的代碼是:
#define REGISTER_UTOBJECT(utName, className) bool b##className = className::RegisterObject(utName);
這行代碼被調用時,對象className將會以utName的名字注冊到對象工廠.
實際上是簡單調用className::RegisiterObject方法.
創建一個className的實例,然后將該實例放置到Factory的數組中.
因為DECLARE_UTOBJECT宏為每個對象定義了Clone方法,所以類工廠可以從該數組中的實例來創建該對象的其他實例.
至于REGISTER_UTOBJECT為什么要定義一個bool b##className對象,完全是因為這樣寫才能通過編譯器檢查. 編譯器讀到className::RegisterObejct(utName)時候,會認為這是在進行一個函數定義而不是進行一個函數調用. 只有明確指定返回值的情況下,才被認為是函數調用.
posted on 2006-05-30 19:43
Jerry Cat 閱讀(1304)
評論(0) 編輯 收藏 引用