XDWRTTI.hpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #pragma once
  2. #include <assert.h>
  3. #ifndef _XDWRTTI_DLL
  4. #define XDWRTTI_API _declspec(dllimport)
  5. #else
  6. #define XDWRTTI_API _declspec(dllexport)
  7. #endif
  8. //-----------------------------------------------------------------------------
  9. //
  10. // 实现自己的 RTTI (Run Time Type Idendify)
  11. //
  12. // 代码改造自 MFC, 但是做了简化
  13. //
  14. //-----------------------------------------------------------------------------
  15. class XDWObject;
  16. struct RTTIClass
  17. {
  18. // Attributes
  19. LPCSTR m_lpszClassName;
  20. int m_nObjectSize;
  21. RTTIClass * m_pBaseClass;
  22. XDWObject * (PASCAL * m_pfnCreateObject) (); // NULL => abstract class
  23. bool IsDerivedFrom (const RTTIClass * pBaseClass) const;
  24. XDWObject * CreateObject ();
  25. };
  26. inline bool RTTIClass::IsDerivedFrom (const RTTIClass * pBaseClass) const
  27. {
  28. assert (this != NULL);
  29. assert (pBaseClass != NULL);
  30. // simple SI case
  31. const RTTIClass * pClassThis = this;
  32. while (pClassThis != NULL)
  33. {
  34. if (pClassThis == pBaseClass)
  35. return true;
  36. pClassThis = pClassThis->m_pBaseClass;
  37. }
  38. return false; // walked to the top, no match
  39. }
  40. #define DECLARE_RTTI(class_name) \
  41. protected: \
  42. static RTTIClass * PASCAL _GetBaseClass (); \
  43. public: \
  44. static const RTTIClass class##class_name; \
  45. static RTTIClass * PASCAL GetThisClass (); \
  46. virtual RTTIClass * GetRTTIClass () const;
  47. // dynamically constructable
  48. #define DECLARE_RTTI_DYNCREATE(class_name) \
  49. DECLARE_RTTI(class_name) \
  50. static XDWObject * PASCAL CreateObject();
  51. #define __IMPLEMENT_RTTI(class_name, base_class_name, func) \
  52. __declspec(selectany) const RTTIClass class_name::class##class_name = { \
  53. #class_name, sizeof(class class_name), RTTI_CLASS (base_class_name), func}; \
  54. RTTIClass * PASCAL class_name::_GetBaseClass() \
  55. { return RTTI_CLASS(base_class_name); } \
  56. RTTIClass * PASCAL class_name::GetThisClass() \
  57. { return _RTTI_CLASS(class_name); } \
  58. RTTIClass * class_name::GetRTTIClass() const \
  59. { return _RTTI_CLASS(class_name); }
  60. #define IMPLEMENT_RTTI(class_name, base_class_name) __IMPLEMENT_RTTI(class_name, base_class_name, NULL)
  61. #define IMPLEMENT_RTTI_DYNCREATE(class_name, base_class_name) \
  62. XDWObject * PASCAL class_name::CreateObject() \
  63. { return new class_name; } \
  64. __IMPLEMENT_RTTI(class_name, base_class_name, class_name::CreateObject)
  65. #define _RTTI_CLASS(class_name) ((RTTIClass *)(&class_name::class##class_name))
  66. #define RTTI_CLASS(class_name) (class_name::GetThisClass())
  67. #define ASSERT_RTTI(class_name, object) ASSERT((object)->IsKindOf(RTTI_CLASS(class_name)))
  68. class XDWRTTI_API XDWObject
  69. {
  70. public:
  71. virtual RTTIClass * GetRTTIClass () const;
  72. virtual ~XDWObject() = 0; // virtual destructors are necessary
  73. protected:
  74. XDWObject ();
  75. private:
  76. XDWObject (const XDWObject & objectSrc); // no implementation
  77. void operator = (const XDWObject & objectSrc); // no implementation
  78. public:
  79. bool IsKindOf (const RTTIClass * pClass) const;
  80. template <typename T> T * As ()
  81. {
  82. if (this != NULL && this->IsKindOf (RTTI_CLASS (T)))
  83. return (T *) this;
  84. else
  85. return NULL;
  86. }
  87. template <typename T> const T * As () const
  88. {
  89. if (this != NULL && this->IsKindOf (RTTI_CLASS (T)))
  90. return (const T *) this;
  91. else
  92. return NULL;
  93. }
  94. template <typename T> bool Is () const
  95. {
  96. return (IsKindOf (RTTI_CLASS (T)));
  97. }
  98. public:
  99. static const RTTIClass classXDWObject;
  100. static RTTIClass * PASCAL _GetBaseClass();
  101. static RTTIClass * PASCAL GetThisClass();
  102. };
  103. inline XDWObject::XDWObject ()
  104. { }
  105. inline XDWObject::~XDWObject ()
  106. { }
  107. inline RTTIClass * XDWObject::GetRTTIClass () const
  108. {
  109. return _RTTI_CLASS (XDWObject);
  110. }
  111. inline RTTIClass * PASCAL XDWObject::_GetBaseClass()
  112. {
  113. return NULL;
  114. }
  115. inline RTTIClass * PASCAL XDWObject::GetThisClass()
  116. {
  117. return _RTTI_CLASS (XDWObject);
  118. }
  119. inline bool XDWObject::IsKindOf (const RTTIClass * pClass) const
  120. {
  121. assert (this != NULL);
  122. // simple SI case
  123. RTTIClass * pClassThis = GetRTTIClass ();
  124. assert (pClassThis);
  125. return pClassThis->IsDerivedFrom (pClass);
  126. }
  127. inline XDWObject * RTTIClass::CreateObject ()
  128. {
  129. assert (this != NULL);
  130. if (m_pfnCreateObject == NULL)
  131. {
  132. assert (false);
  133. return NULL;
  134. }
  135. XDWObject * pObject = NULL;
  136. try
  137. {
  138. pObject = (*m_pfnCreateObject) ();
  139. }
  140. catch (...)
  141. {
  142. }
  143. return pObject;
  144. }