Решил перепостить в свой блог подсказку, которую я писал на сайте Gamedev.ru (здесь), и заодно немного подправить
Простой аналог 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) \
- typedef Self 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)
- };
-
- class SecondChildObject : public ChildObject
- {
- public:
- DECLARE_OBJECT(SecondChildObject)
- };
-
- 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
Замечание: Данный метод не работает при наследовании от нескольких базовых классов...
* Подсветка синтаксиса http://quickhighlighter.com