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