#pragma once #include #ifndef _XDWRTTI_DLL #define XDWRTTI_API _declspec(dllimport) #else #define XDWRTTI_API _declspec(dllexport) #endif //----------------------------------------------------------------------------- // // 实现自己的 RTTI (Run Time Type Idendify) // // 代码改造自 MFC, 但是做了简化 // //----------------------------------------------------------------------------- class XDWObject; struct RTTIClass { // Attributes LPCSTR m_lpszClassName; int m_nObjectSize; RTTIClass * m_pBaseClass; XDWObject * (PASCAL * m_pfnCreateObject) (); // NULL => abstract class bool IsDerivedFrom (const RTTIClass * pBaseClass) const; XDWObject * CreateObject (); }; inline bool RTTIClass::IsDerivedFrom (const RTTIClass * pBaseClass) const { assert (this != NULL); assert (pBaseClass != NULL); // simple SI case const RTTIClass * pClassThis = this; while (pClassThis != NULL) { if (pClassThis == pBaseClass) return true; pClassThis = pClassThis->m_pBaseClass; } return false; // walked to the top, no match } #define DECLARE_RTTI(class_name) \ protected: \ static RTTIClass * PASCAL _GetBaseClass (); \ public: \ static const RTTIClass class##class_name; \ static RTTIClass * PASCAL GetThisClass (); \ virtual RTTIClass * GetRTTIClass () const; // dynamically constructable #define DECLARE_RTTI_DYNCREATE(class_name) \ DECLARE_RTTI(class_name) \ static XDWObject * PASCAL CreateObject(); #define __IMPLEMENT_RTTI(class_name, base_class_name, func) \ __declspec(selectany) const RTTIClass class_name::class##class_name = { \ #class_name, sizeof(class class_name), RTTI_CLASS (base_class_name), func}; \ RTTIClass * PASCAL class_name::_GetBaseClass() \ { return RTTI_CLASS(base_class_name); } \ RTTIClass * PASCAL class_name::GetThisClass() \ { return _RTTI_CLASS(class_name); } \ RTTIClass * class_name::GetRTTIClass() const \ { return _RTTI_CLASS(class_name); } #define IMPLEMENT_RTTI(class_name, base_class_name) __IMPLEMENT_RTTI(class_name, base_class_name, NULL) #define IMPLEMENT_RTTI_DYNCREATE(class_name, base_class_name) \ XDWObject * PASCAL class_name::CreateObject() \ { return new class_name; } \ __IMPLEMENT_RTTI(class_name, base_class_name, class_name::CreateObject) #define _RTTI_CLASS(class_name) ((RTTIClass *)(&class_name::class##class_name)) #define RTTI_CLASS(class_name) (class_name::GetThisClass()) #define ASSERT_RTTI(class_name, object) ASSERT((object)->IsKindOf(RTTI_CLASS(class_name))) class XDWRTTI_API XDWObject { public: virtual RTTIClass * GetRTTIClass () const; virtual ~XDWObject() = 0; // virtual destructors are necessary protected: XDWObject (); private: XDWObject (const XDWObject & objectSrc); // no implementation void operator = (const XDWObject & objectSrc); // no implementation public: bool IsKindOf (const RTTIClass * pClass) const; template T * As () { if (this != NULL && this->IsKindOf (RTTI_CLASS (T))) return (T *) this; else return NULL; } template const T * As () const { if (this != NULL && this->IsKindOf (RTTI_CLASS (T))) return (const T *) this; else return NULL; } template bool Is () const { return (IsKindOf (RTTI_CLASS (T))); } public: static const RTTIClass classXDWObject; static RTTIClass * PASCAL _GetBaseClass(); static RTTIClass * PASCAL GetThisClass(); }; inline XDWObject::XDWObject () { } inline XDWObject::~XDWObject () { } inline RTTIClass * XDWObject::GetRTTIClass () const { return _RTTI_CLASS (XDWObject); } inline RTTIClass * PASCAL XDWObject::_GetBaseClass() { return NULL; } inline RTTIClass * PASCAL XDWObject::GetThisClass() { return _RTTI_CLASS (XDWObject); } inline bool XDWObject::IsKindOf (const RTTIClass * pClass) const { assert (this != NULL); // simple SI case RTTIClass * pClassThis = GetRTTIClass (); assert (pClassThis); return pClassThis->IsDerivedFrom (pClass); } inline XDWObject * RTTIClass::CreateObject () { assert (this != NULL); if (m_pfnCreateObject == NULL) { assert (false); return NULL; } XDWObject * pObject = NULL; try { pObject = (*m_pfnCreateObject) (); } catch (...) { } return pObject; }