C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
оцените самодельный rtti, а именно dynamic_cast
Георгий
Отправлено: 05.05.2005, 22:43


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



сижу под своим QNX4 с древним компилятором Wactom 10.6, во времена рождения которого никто об RTTI и не задумывался. вот от такой жизни и реализовал аналог dynamic_cast, причём старался сохранить и сходство синтаксиса.

наверняка в моей реализации есть ляпы и хотелось бы их, с вашей помощью, увидеть.

при использовании нормального компилятора с поддержкой RTTI:
CODE
class A{};
class B{};
class C:public A,public B{};

{
C c;
A* ptrA = &c;//работа по интерфейсу A
B* ptrB = dynamic_cast<B>(ptrA);// получение доступа к интерфейсу B объекта, скрывающегося за интерфейсом A
};


при использовании моей самоделки:
CODE
class A:public_dynamic_cast_base
{
DYNAMIC_CAST_SUPPORT_DECLARE;
};
class B:public_dynamic_cast_base
{
DYNAMIC_CAST_SUPPORT_DECLARE;
};
class C:public A,public B
{
DYNAMIC_CAST_SUPPORT_DECLARE;
};

//в cpp файлах с реализацией классов A, B и C
//a.cpp
DYNAMIC_CAST_SUPPORT_IMPLEMENT_1PARENT( A, dynamic_cast_base );
//b.cpp
DYNAMIC_CAST_SUPPORT_IMPLEMENT_1PARENT( B, dynamic_cast_base );
//c.cpp
DYNAMIC_CAST_SUPPORT_IMPLEMENT_2PARENT( C, A, B );

//основная программа
{
C c;
A* ptrA = &c;//работа по интерфейсу A
B* ptrB = dynamic_cast<B>(ptrA);// получение доступа к интерфейсу B объекта, скрывающегося за интерфейсом A
};


текст модуля реализации RTTI:
CODE
#ifndef CAST_H_INCLUDED
#define CAST_H_INCLUDED

#include <string>

#include <UtilsSGV/PragmaPack>

template <class T>
class dynamic_cast;

class dynamic_cast_base
{
public:
virtual const String& GetClassName(void)const=0;
protected:
virtual void * Cast(const String&){return 0;};
friend class dynamic_cast;
};

template <class T>
class dynamic_cast
{
private:
dynamic_cast_base* hdc;
dynamic_cast( void ):hdc(0){};
public:
dynamic_cast( dynamic_cast_base* hdc ):hdc(hdc){};

operator T* ()const
 {return (*this)(this->hdc);};

T* operator()( dynamic_cast_base* hdc )const
 {
 const String& name = T::ClassName;
 
 return (T*)((hdc)?(hdc->Cast(name)):0);
 };
};

#define DYNAMIC_CAST_SUPPORT_DECLARE\
public: static const String ClassName;\
public: virtual const String& GetClassName(void)const;\
protected: void* Cast(const String& str);
 
#define DYNAMIC_CAST_SUPPORT_BASE_IMPLEMENT( className )\
static const String className::ClassName( #className );\
const String& className::GetClassName(void)const{return className::ClassName;};\
void* className::Cast(const String& str)

#define DYNAMIC_CAST_SUPPORT_IMPLEMENT_1PARENT( className, baseClass )\
 DYNAMIC_CAST_SUPPORT_BASE_IMPLEMENT( className )\
 {void * ret = (str==className::ClassName)?this:baseClass::Cast(str);\
 return ret;};

#define DYNAMIC_CAST_SUPPORT_IMPLEMENT_2PARENT( className, baseClass1, baseClass2 )\
 DYNAMIC_CAST_SUPPORT_BASE_IMPLEMENT( className )\
 {void *self = (str==ClassName)?this:0;\
 void *left = baseClass1::Cast(str);\
 void *right= baseClass2::Cast(str);\
 void *ret  = self?self:(left?left:right);\
 return ret;};

#define DYNAMIC_CAST_SUPPORT_IMPLEMENT_3PARENT( className, baseClass1, baseClass2, baseClass3 )\
 DYNAMIC_CAST_SUPPORT_BASE_IMPLEMENT( className )\
 {void *self = (str==ClassName)?this:0;\
 void *left = baseClass1::Cast(str);\
 void *right= baseClass2::Cast(str);\
 void *middle= baseClass3:Cast(str);\
 void *ret  = self?self:(left?left:(right?right:middle));\
 return ret;};
 
#define DYNAMIC_CAST_TEMPLATES_SUPPORT_BASE_IMPLEMENT( test_template )\
template <class T>\
static const String test_template<T>::ClassName(  String( #test_template )+"<" + T::ClassName + ">");\
template <class T>\
const String& test_template<T>::GetClassName(void)const{return test_template<T>::ClassName;};\
template <class T>\
void * test_template<T>::Cast(const String& str){\
 void *self = (str==test_template<T>::ClassName)?this:0;

#define DYNAMIC_CAST_TEMPLATES_SUPPORT_IMPLEMENT_1PARENT( test_template, base1 )\
DYNAMIC_CAST_TEMPLATES_SUPPORT_BASE_IMPLEMENT( test_template )\
void *left = base1::Cast(str);\
void *right= T::Cast(str);\
void *ret  = self?self:(left?left:right);\
return ret;};

#include <UtilsSGV/PragmaPop>

#endif

Вернуться в Аспекты и идеология профессиональной разработки ПО