XDWRTTI.hpp 4.6 KB

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