Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Подсказки / Простой аналог dynamic_cast и RTTI

Простой аналог dynamic_cast и RTTI

Поделиться

Автор:

Простой аналог dynamic_cast и RTTI для тех, кто не хочет, по каким-либо религиозным причинам, использовать встроенный...

class CType
{
  const CType*  mSuper;
  const char*    mName;
public:
  CType( const CType* parent, const char* name ): mSuper(parent), mName(name) {}

  inline bool Is( const CType* objtype ) const
  {
    while( objtype && objtype != this )
    {
      objtype = objtype->mSuper;
    }
    return objtype == this;
  }

  inline const char* GetName() const { return mName; }
};

#define DECLARE_GET_TYPE(cls)      \
    typedef cls  Self;    \
    virtual const CType*  GetType() const { return &Type(); }

#define DECLARE_OBJECT(cls,super)    \
    typedef super  Super;    \
    static inline const CType&  Type() { static const CType my_type( &cls::Super::Type(), #cls ); return my_type; }  \
    DECLARE_GET_TYPE(cls)
          
#define DECLARE_ROOT_OBJECT(cls)            \
    static inline const CType&  Type() { static const CType my_type( 0, #cls ); return my_type; } \
    DECLARE_GET_TYPE(cls)             \
    template <class T> static inline T* Cast( cls * obj )      \
    {                \
      return GET_CLASS_TYPE(T)->Is( GET_OBJECT_TYPE(obj) ) ? (T*)obj : NULL;  \
    }                \
    \
    template <class T> static inline const T* Cast( const cls * obj )  \
    {                \
      return GET_CLASS_TYPE(T)->Is( GET_OBJECT_TYPE(obj) ) ? (T*)obj : NULL;  \
    }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define GET_CLASS_TYPE(cls) (&cls::Type())
#define GET_CLASS_TYPE_NAME(cls) (GET_CLASS_TYPE(cls)->GetName())

#define GET_OBJECT_TYPE(obj) (obj->GetType())
#define GET_OBJECT_TYPE_NAME(obj) (GET_OBJECT_TYPE(obj)->GetName())
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

пример использования

#include <iostream> 

class Object
{
public:
  DECLARE_ROOT_OBJECT(Object)
  
};

class ChildObject : public Object
{
public:
  DECLARE_OBJECT(ChildObject, Object)
};

class SecondChildObject : public ChildObject
{
public:
  DECLARE_OBJECT(SecondChildObject, ChildObject)
};

int main()
{
  const Object *o1 = new Object(), *o2 = new ChildObject(), *o3 = new SecondChildObject();
  const ChildObject* derived = 0;
  const SecondChildObject* secondderived = 0;

  std::cout<< "o1 is " << GET_OBJECT_TYPE_NAME( o1 ) << std::endl;
  std::cout<< "o2 is " << GET_OBJECT_TYPE_NAME( o2 ) << std::endl;
  std::cout<< "o3 is " << GET_OBJECT_TYPE_NAME( o3 ) << std::endl << std::endl;

  derived = Object::Cast<ChildObject>(o1);
  std::cout<< "o1 is " << (derived == 0 ? "not ": "") << GET_CLASS_TYPE_NAME(ChildObject) << std::endl;
  derived = Object::Cast<ChildObject>(o2);
  std::cout<< "o2 is " << (derived == 0 ? "not ": "") << GET_CLASS_TYPE_NAME(ChildObject) << std::endl;
  derived = Object::Cast<ChildObject>(o3);
  std::cout<< "o3 is " << (derived == 0 ? "not ": "") << GET_CLASS_TYPE_NAME(ChildObject) << std::endl << std::endl;

  
  secondderived = Object::Cast<SecondChildObject>(o1);
  std::cout<< "o1 is " << (secondderived == 0 ? "not ": "") << GET_CLASS_TYPE_NAME(SecondChildObject) << std::endl;
  secondderived = Object::Cast<SecondChildObject>(o2);
  std::cout<< "o2 is " << (secondderived == 0 ? "not ": "") << GET_CLASS_TYPE_NAME(SecondChildObject) << std::endl;
  secondderived = Object::Cast<SecondChildObject>(o3);
  std::cout<< "o3 is " << (secondderived == 0 ? "not ": "") << GET_CLASS_TYPE_NAME(SecondChildObject) << std::endl << std::endl;

  return 0;
}

output:

o1 is Object
o2 is ChildObject
o3 is SecondChildObject

o1 is not ChildObject
o2 is ChildObject
o3 is ChildObject

o1 is not SecondChildObject
o2 is not SecondChildObject
o3 is SecondChildObject

Замечание: Данный метод не работает при наследовании от нескольких базовых классов...

30 декабря 2009

#C++, #RTTI

2001—2017 © GameDev.ru — Разработка игр