Почетный железнодорожник
Группа: Модератор
Сообщений: 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 | |