class IObject {
public:
virtual bool Method() = 0;
template<class T> T * As() { return (T*)this; } // да-да, не dynamic_cast.
}
class Object1 : public IObject {
public: virtual bool Method() { /* some logic */ }
}
class Object2 : public IObject {
public: virtual bool Method() { /* some logic */ }
}
class NamedObject : public IObject {
public:
NamedObject(const std::string& nm, IObject * o) : name(nm), obj(o) {}
virtual bool Method() { return obj->Method(); }
std::string& Name() { return name; }
IObject * Object() { return obj; }
private:
IObject * obj;
std::string name;
}
template<typename T>
inline bool isA(IObject * obj)
{
return dynamic_cast<T*>(obj) != null ||
(isA<NamedObject>(obj) && isA<T>(obj->As<NamedObject>()->Object()));
}
template<>
inline bool isA<NamedObject>(IObject * obj)
{
return dynamic_cast< NamedObject* >(obj) != null;
}
#include <iostream>
class TypeIdGenerator
{
public:
template <typename T>
static const int GetId()
{
static const int Id = GetNextId();
return Id;
}
private:
static int GetNextId()
{
static int Id = 0;
return Id++;
}
};
struct ICast
{
virtual ~ICast()
{
}
virtual void const* Cast(int id) const = 0;
virtual void * Cast(int id) = 0;
};
template <typename T>
class CastImpl
: public T
{
public:
virtual void const* Cast(int id) const
{
return id == TypeIdGenerator::GetId<T>() ? this : 0;
}
virtual void * Cast(int id)
{
return id == TypeIdGenerator::GetId<T>() ? this : 0;
}
};
template <typename T>
T* MyCast(ICast *obj)
{
return reinterpret_cast<T *>(obj->Cast(TypeIdGenerator::GetId<T>()));
}
template <typename T>
T const* MyCast(ICast const *obj)
{
return reinterpret_cast<T const *>(obj->Cast(TypeIdGenerator::GetId<T>()));
}
class A
: public ICast
{
public:
void mtd() const
{
std::cout << __FUNCTION__ << std::endl;
}
};
int main()
{
ICast const &obj = CastImpl<A>();
A const *a = MyCast<A>(&obj);
if (a)
a->mtd();
return 0;
}
typedef std::unique_ptr< IObject > ptr;INamedObject наследуется также реализует IObject
ptr p = CreateObject< Object3 >();
assert( FastObjectCast< Object3 >( p.get() ) );
assert( FastObjectCast< Object1 >( p.get() ) ); // Object3 inherits Object1
assert( !FastObjectCast< INamedObject >( p.get() ) ); // p is unnamed Object3
ptr q = CreateObject< Object3 >( "some name" );
assert( FastObjectCast< Object3 >( q.get() ) );
assert( FastObjectCast< Object1 >( q.get() ) ); // Object3 inherits Object1
assert( FastObjectCast< INamedObject >( q.get() ) ); // p is named Object3
template<class T> T * As() { return (T*)this; }Нужно использовать static_cast, т.к. после каста указатель может поменять значение на пару байт (это происходит из-за множественного наследования, если оно есть в иерархии).