#pragma once #include //#include #include #ifndef _XDWRTTI_DLL #define XDWRTTI_API _declspec(dllimport) #else #define XDWRTTI_API _declspec(dllexport) #endif //----------------------------------------------------------------------------- // // 实现自己的 RTTI (Run Time Type Idendify) // // 代码改造自 MFC, 但是做了简化 // //----------------------------------------------------------------------------- class RTTIObject; struct RTTIClass { // using _tClassName = std::string_view; using _tClassName = const char *; // Attributes _tClassName m_lpszClassName; // 目前没啥用途, 因此不用 string_view 来存储了. int m_nObjectSize; RTTIClass * m_pBaseClass; RTTIObject * (PASCAL * m_pfnCreateObject) (); // NULL => abstract class bool IsDerivedFrom (const RTTIClass * pBaseClass) const; RTTIObject * 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 RTTIObject * 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() \ { \ static_assert (std::is_base_of ::value, \ "class " #class_name " is NOT derived from class " #base_class_name); \ 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) \ RTTIObject * 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 RTTIObject { public: virtual RTTIClass * GetRTTIClass () const; virtual ~RTTIObject() = 0; // virtual destructors are necessary protected: RTTIObject (); private: RTTIObject (const RTTIObject & objectSrc); // no implementation void operator = (const RTTIObject & 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 classRTTIObject; static RTTIClass * PASCAL _GetBaseClass(); static RTTIClass * PASCAL GetThisClass(); }; inline RTTIObject::RTTIObject () { } inline RTTIObject::~RTTIObject () { } inline RTTIClass * RTTIObject::GetRTTIClass () const { return _RTTI_CLASS (RTTIObject); } inline RTTIClass * PASCAL RTTIObject::_GetBaseClass() { return NULL; } inline RTTIClass * PASCAL RTTIObject::GetThisClass() { return _RTTI_CLASS (RTTIObject); } inline bool RTTIObject::IsKindOf (const RTTIClass * pClass) const { assert (this != NULL); // simple SI case RTTIClass * pClassThis = GetRTTIClass (); assert (pClassThis); return pClassThis->IsDerivedFrom (pClass); } inline RTTIObject * RTTIClass::CreateObject () { assert (this != NULL); if (m_pfnCreateObject == NULL) { assert (false); return NULL; } RTTIObject * pObject = NULL; try { pObject = (*m_pfnCreateObject) (); } catch (...) { } return pObject; }