Refl.h #pragma once #include "rtti.h" #include <string> #include <map> #include <stdio.h> #include <stdarg.h> using namespace std; template<typename T> struct STypeSizeWrapper { enum { typesize = sizeof(T), }; }; template<> struct STypeSizeWrapper<SNullType> { enum { typesize = 0, }; }; template<typename T1 = SNullType, typename T2 = SNullType, typename T3 = SNullType, typename T4 = SNullType, typename T5 = SNullType, typename T6 = SNullType, typename T7 = SNullType> struct STypeSplit { enum { argSize = STypeSizeWrapper<T1>::typesize + STypeSizeWrapper<T2>::typesize + STypeSizeWrapper<T3>::typesize + STypeSizeWrapper<T4>::typesize + STypeSizeWrapper<T5>::typesize + STypeSizeWrapper<T6>::typesize +STypeSizeWrapper<T7>::typesize , }; }; template<typename T1 = SNullType, typename T2 = SNullType, typename T3 = SNullType, typename T4 = SNullType, typename T5 = SNullType, typename T6 = SNullType, typename T7 = SNullType> struct SFunExtractBase { enum { argSize = STypeSplit<T1, T2, T3, T4, T5, T6, T7>::argSize, }; }; template <class R , class T0> int function_argsize(R (__thiscall T0::*)()) { return SFunExtractBase<SNullType>::argSize; } template <class R , class T0, class T1 > int function_argsize(R (__thiscall T0::*)(T1)) { return SFunExtractBase<T1>::argSize; } template <class R , class T0, class T1, class T2 > int function_argsize(R (__thiscall T0::*)(T1, T2)) { return SFunExtractBase<T1, T2>::argSize; } template <class R , class T0, class T1, class T2 , class T3> int function_argsize(R (__thiscall T0::*)(T1, T2, T3)) { return SFunExtractBase<T1, T2, T3>::argSize; } template <class R , class T0, class T1, class T2 , class T3, class T4> int function_argsize(R (__thiscall T0::*)(T1, T2, T3, T4)) { return SFunExtractBase<T1, T2, T3, T4>::argSize; } template <class R , class T0, class T1, class T2 , class T3, class T4, class T5> int function_argsize(R (__thiscall T0::*)(T1, T2, T3, T4, T5)) { return SFunExtractBase<T1, T2, T3, T4, T5>::argSize; } template <class R , class T0, class T1, class T2 , class T3, class T4, class T5, class T6> int function_argsize(R (__thiscall T0::*)(T1, T2, T3, T4, T5, T6)) { return SFunExtractBase<T1, T2, T3, T4, T5, T6>::argSize; } template <class R , class T0, class T1, class T2 , class T3, class T4, class T5, class T6, class T7> int function_argsize(R (__thiscall T0::*)(T1, T2, T3, T4, T5, T6, T7)) { return SFunExtractBase<T1, T2, T3, T4, T5, T6, T7>::argSize; } template<typename T, int a> struct SCallFunWithArg { typedef struct Tmp { char arg[a]; } ARGTYPE; typedef void (T::*Prt)(ARGTYPE); static void callwitharg(T* pObj, Prt fun, int nSize, va_list arg_ptr) { if (a < nSize) { return SCallFunWithArg<T, a+1>::callwitharg(pObj, SCallFunWithArg<T, a+1>::Prt(fun), nSize, arg_ptr); } else if (a > nSize) { return SCallFunWithArg<T, a-1>::callwitharg(pObj, SCallFunWithArg<T, a-1>::Prt(fun), nSize, arg_ptr); } else { ARGTYPE arg = *((ARGTYPE*)arg_ptr); return (pObj->*fun)(arg); } } }; #define MAX_ARGSIZE 256 #define MAX_ARGSIZE_TEST 128 template<typename T> struct SCallFunWithArg<T, MAX_ARGSIZE> { typedef struct Tmp { char arg[MAX_ARGSIZE]; } ARGTYPE; typedef void (T::*Prt)(ARGTYPE); static void callwitharg(T* pObj, Prt fun, int nSize, va_list arg_ptr) { ARGTYPE arg = *((ARGTYPE*)arg_ptr); return (pObj->*fun)(arg); } }; template<typename T> struct SCallFunWithArg<T, 0> { typedef void (T::*Prt)(); static void callwitharg(T* pObj, Prt fun, int nSize, va_list arg_ptr) { return (pObj->*fun)(); } }; #define METHOD_DECL(classname) / protected: / typedef void (classname::*Prt)(char*);/ map<string, pair<int, Prt> > m_funmap;/ public:/ void CallFun(char* funname, ...)/ {/ va_list arg_ptr; / va_start(arg_ptr, funname); / map<string, pair<int, Prt> >::iterator it = m_funmap.find(funname);/ if (it != m_funmap.end())/ {/ int nSize = (*it).second.first;/ Prt p = it->second.second;/ SCallFunWithArg<classname, MAX_ARGSIZE_TEST>::callwitharg(this, SCallFunWithArg<classname, MAX_ARGSIZE_TEST>::Prt(p), nSize, arg_ptr);/ } / va_end(arg_ptr); / } // #define REGISTER_METHOD(classnamefun)/ m_funmap[#classnamefun] = make_pair<int, Prt>(function_argsize(&classnamefun), (Prt)&classnamefun); rtti.h #pragma once class CObjBase { public: virtual ~CObjBase(){} virtual void CallFun(char* funname, ...) = 0; virtual const char* getClassName() =0; }; #define RTTI_DEL(x) / virtual const char* getClassName()/ {/ return m_classname;/ }/ static char* m_classname ; #define RTTI_IMP(x) / char* x::m_classname=#x ; struct SNullType { }; template <class T, class U> class Conversion { typedef char Small; class Big { char dummy[2]; }; static Small Test(U); static Big Test(...); static T MakeT(); public: enum { exists = sizeof(Test(MakeT())) == sizeof(Small) }; enum { sameType = false }; }; template<typename T, typename U = SNullType> struct Typelist { typedef T Head; typedef U Tail; template<typename SuperClass> static bool IsKindOf(const char *pName) { if (strcmp(Head::m_classname, pName) == 0 ) { return Conversion<Head*, SuperClass*>::exists; } else { return Tail::IsKindOf<SuperClass>(pName ); } } static CObjBase* CreatObj(const char *pName) { if (strcmp(Head::m_classname, pName) == 0 ) { return new Head; } else { return Tail::CreatObj(pName ); } } }; template <typename T> struct Typelist< T, SNullType> { public: typedef T Type; template<typename SuperClass> static bool IsKindOf(const char *pName) { if ( strcmp(Type::m_classname, pName) == 0 ) { return Conversion<Type*, SuperClass*>::exists; } else { return false; } } static CObjBase* CreatObj(const char *pName) { if (strcmp(Type::m_classname, pName) == 0 ) { return new Type; } else { return NULL; } } }; #define TYPELIST_1(T1) Typelist<T1, SNullType> #define TYPELIST_2(T1, T2) Typelist<T1, TYPELIST_1(T2) > #define TYPELIST_3(T1, T2, T3) Typelist<T1, TYPELIST_2(T2, T3) > #define TYPELIST_4(T1, T2, T3, T4) / Typelist<T1, TYPELIST_3(T2, T3, T4) > #define TYPELIST_5(T1, T2, T3, T4, T5) / Typelist<T1, TYPELIST_4(T2, T3, T4, T5) > #define TYPELIST_6(T1, T2, T3, T4, T5, T6) / Typelist<T1, TYPELIST_5(T2, T3, T4, T5, T6) > #define TYPELIST_7(T1, T2, T3, T4, T5, T6, T7) / Typelist<T1, TYPELIST_6(T2, T3, T4, T5, T6, T7) > #define TYPELIST_8(T1, T2, T3, T4, T5, T6, T7, T8) / Typelist<T1, TYPELIST_7(T2, T3, T4, T5, T6, T7, T8) > #define TYPELIST_9(T1, T2, T3, T4, T5, T6, T7, T8, T9) / Typelist<T1, TYPELIST_8(T2, T3, T4, T5, T6, T7, T8, T9) > typelistDef.h #pragma once #include "rtti.h" class CGraphInstConcrete; class CActor; class CGameObj; class CGraphInst; typedef TYPELIST_4(CGraphInstConcrete, CActor, CGameObj, CGraphInst) mytypelist; template<class SuperClass> bool IsKindOf(const char* pA) { return mytypelist::IsKindOf<SuperClass>(pA); } CObjBase* CreateObj(const char* pA) { return mytypelist::CreatObj(pA); } test.cpp // testRel.cpp : Defines the entry point for the console application. // #include "Refl.h" #include "typelistDef.h" #include <iostream> #include <string> using namespace std; class CGraphInst:public CObjBase { public: RTTI_DEL(CGraphInst); METHOD_DECL(CGraphInst); }; RTTI_IMP(CGraphInst); class CGraphInstConcrete: public CGraphInst { public: RTTI_DEL(CGraphInstConcrete); METHOD_DECL(CGraphInstConcrete); void test() { cout << "CGraphInstConcrete::test"; } }; RTTI_IMP(CGraphInstConcrete); class CGameObj : virtual public CObjBase { public: RTTI_DEL(CGameObj); METHOD_DECL(CGameObj); CGameObj() { REGISTER_METHOD(CGameObj::testFun); REGISTER_METHOD(CGameObj::testFun2); } void testFun(int a, CGraphInstConcrete* gi, int b) { cout << a << "," << b << endl; gi->test(); } void testFun2(int a) { cout << "testFun2" << endl; } }; RTTI_IMP(CGameObj); class CActor1 : virtual public CObjBase { public: RTTI_DEL(CActor1); METHOD_DECL(CActor1); }; RTTI_IMP(CActor1); class CActor : virtual public CGameObj,virtual public CActor1 { public: RTTI_DEL(CActor); METHOD_DECL(CActor); }; RTTI_IMP(CActor); int _tmain(int argc, _TCHAR* argv[]) { CObjBase* pObjActor = CreateObj("CActor"); CObjBase* pObjGameObj = CreateObj("CGameObj"); CObjBase* pObjGIC = CreateObj("CGraphInstConcrete"); CObjBase* pObjGI = CreateObj("CGraphInst"); pObjGameObj->CallFun("CGameObj::testFun", 11, pObjGIC, 22); pObjGameObj->CallFun("CGameObj::testFun2", 11); cout << IsKindOf<CActor>(pObjActor->getClassName()) << endl; cout << IsKindOf<CGameObj>(pObjActor->getClassName()) << endl; cout << IsKindOf<CActor>(pObjGameObj->getClassName()) << endl; cout << IsKindOf<CActor>(pObjGIC->getClassName()) << endl; cout << IsKindOf<CActor1>(pObjActor->getClassName()) << endl; cout << IsKindOf<CGameObj>(pObjActor->getClassName()) << endl; return 0; }