游戏开发论坛

 找回密码
 立即注册
搜索
查看: 3096|回复: 6

[2.0版]回调类中动态成员

[复制链接]

362

主题

3023

帖子

3553

积分

论坛元老

Rank: 8Rank: 8

积分
3553
发表于 2008-1-14 03:06:00 | 显示全部楼层 |阅读模式
更新说明:

1.0版没有使用template,稍微麻烦了1点,现在改过来了。

1.0版有个痛苦的bug:
假如有一个类,使用了多继承(包括接口多继承!这是最可恶的!)
CMyClass:public Base1,public Base2
void CMyClass::Func(void);//这个函数是唯一的!基类里面没有!不是歧义问题!
然后
omf = (void(__obj:: *)(void)) &CMyClass::Func()
就出错。所以只有用汇编!
虽然没有歧义,但是多继承的类的成员函数,就是不允许类型转换。


//instEvent.h
#ifndef INST_EVENT_H
#define INST_EVENT_H


#include <instTypes.h>
#include <instDefines.h>

#include <instList.h>


namespace inst
{



template <typename T> class CEvent
{
public:
        typedef struct
        {
                __obj* pThis;
                T pFunc;
        }INSTCALLBACK;
        ArrayList<INSTCALLBACK*> m_CallBacks;
        template <class F> void AddCallBack(void* pThis,F clsFunc)
        {
                T objFunc=union_cast<T>(clsFunc);
                for(UInt32 i=0;i<m_CallBacks.Count();i++)
                        if(m_CallBacks.Get(i)->pThis==(__obj *)pThis||
                                m_CallBacks.Get(i)->pFunc==objFunc) return;
                INSTCALLBACK* tmp=new INSTCALLBACK;
                tmp->pThis=(__obj *)pThis;
                tmp->pFunc=objFunc;
                m_CallBacks.Add(tmp);
        }
        template <class F> void RemoveCallBack(void* pThis,F clsFunc)
        {
                T objFunc=union_cast<T>(clsFunc);
                for(UInt32 i=0;i<m_CallBacks.Count();i++)
                        if(m_CallBacks.Get(i)->pThis==(__obj *)pThis||m_CallBacks.Get(i)->pFunc==objFunc)
                                m_CallBacks.Remove(i);
        }
        T GetFunc(UInt32 n)
        {
                return m_CallBacks.Get(n)->pFunc;
        }
};

#define DeclareEvent(event,types)        CEvent<void (__obj::*)types> event

#define RaiseEvent(event,params)        {for(UInt32 _i_=0;_i_<(event).m_CallBacks.Count();_i_++)                ((event).m_CallBacks.Get(_i_)->pThis->*((event).GetFunc(_i_)))params;}


}//end of namespace inst


#endif//INST_EVENT_H

362

主题

3023

帖子

3553

积分

论坛元老

Rank: 8Rank: 8

积分
3553
 楼主| 发表于 2008-1-14 03:07:00 | 显示全部楼层

Re:[2.0版]回调类中动态成员

编译这个,需要
instTypes.h
instDefines.h
instList.h
具体的在下面:

//instTypes.h
#ifndef INST_TYPES_H
#define INST_TYPES_H


namespace inst
{
        //为了输入方便,基本数据类型只是首字母大写
        //但inst命名空间中其他的typedef一律全部大写!
        //在inst命名空间里,基本数据类型一律用这些typedef。

        //这些定义在win32下是完全可用的,
        //但是其他平台则应该使用其他头文件

        typedef char                        Byte;
        typedef short                        Int16;
        typedef long                        Int32;
        typedef bool                        Bool;
        typedef float                        Float;
        typedef double                        Double;

        typedef unsigned char        UByte;
        typedef unsigned short        UInt16;
        typedef unsigned long        UInt32;

//有的编译器对wchat_t没有定义
//但是,不能擅自地直接使用unsigned short来定义WChar,
//因为在有的编译器里,wchar_t不等于unsigned short
#ifndef _WCHAR_T_DEFINED
typedef unsigned short wchar_t;
//#define _WCHAR_T_DEFINED
#endif

        typedef char                        Char;        //在win32平台,等同于CHAR而无需类型转换
        typedef wchar_t                        WChar;        //在win32平台,等同于WCHAR而无需类型转换

        const Bool True                =        true;
        const Bool False        =        false;

}


#endif

362

主题

3023

帖子

3553

积分

论坛元老

Rank: 8Rank: 8

积分
3553
 楼主| 发表于 2008-1-14 03:07:00 | 显示全部楼层

Re:[2.0版]回调类中动态成员

//instDefines.h
#ifndef INST_DEFINES_H
#define INST_DEFINES_H


#ifdef NULL
#undef NULL
#endif
#define NULL 0

#ifdef null
#undef null
#endif
#define null 0

#ifdef Null
#undef Null
#endif
#define Null 0


#ifdef SAFEDEL
#undef SAFEDEL
#endif
#define SAFEDEL(x) if(x) delete x

#ifdef safedel
#undef safedel
#endif
#define safedel(x) if(x) delete x

#ifdef SafeDel
#undef SafeDel
#endif
#define SafeDel(x) if(x) delete x


#ifdef SAFEDELARRAY
#undef SAFEDELARRAY       
#endif
#define SAFEDELARRAY(x) if(x) delete[] x

#ifdef safedelarray
#undef safedelarray
#endif
#define safedelarray(x) if(x) delete[] x

#ifdef SafeDelArray
#undef SafeDelArray
#endif
#define SafeDelArray(x) if(x) delete[] x


#ifdef SAFERELEASE
#undef SAFERELEASE
#endif
#define SAFERELEASE(x) if(x) x->Release()

#ifdef saferelease
#undef saferelease
#endif
#define saferelease(x) if(x) x->Release()

#ifdef SafeRelease
#undef SafeRelease
#endif
#define SafeRelease(x) if(x) x->Release()


#ifdef MIN
#undef MIN
#endif
#define MIN(x,y)        ((x)<(y)?(x)y))

#ifdef min
#undef min
#endif
#define min(x,y)        ((x)<(y)?(x):(y))

#ifdef Min
#undef Min
#endif
#define Min(x,y)        ((x)<(y)?(x):(y))


#ifdef MAX
#undef MAX
#endif
#define MAX(x,y)        ((x)>(y)?(x):(y))

#ifdef max
#undef max
#endif
#define max(x,y)        ((x)>(y)?(x):(y))

#ifdef Max
#undef Max
#endif
#define Max(x,y)        ((x)>(y)?(x):(y))


#ifdef GET_SET
#undef GET_SET
#endif

#define GET_SET(p1,p2,p3,type,x,g,s)p1: type x;p2: type g()const{return x;}p3: void s(type val){x=val;}

#ifdef Get_Set
#undef Get_Set
#endif
#define Get_Set GET_SET

#ifdef get_set
#undef get_set
#endif       
#define Get_Set GET_SET


#ifdef GET_SET_Q
#undef GET_SET_Q
#endif
#define GET_SET_Q(type,x,g,s) GET_SET(private,public,public,type,x,g,s)

#ifdef Get_Set_Q
#undef Get_Set_Q
#endif
#define Get_Set_Q GET_SET_Q

#ifdef get_set_q
#undef get_set_q
#endif
#define get_set_q GET_SET_Q
       
template <class dest, class src> struct _UNIONCAST
{
        union
        {
                dest d;
                src s;
        };
};

template <class dest, class src> dest union_cast(src s)
{
        _UNIONCAST<dest,src> tmp;
        tmp.s=s;
        return tmp.d;
}


#include <instTypes.h>


namespace inst
{


class __obj{};

typedef Int32 POS;
typedef UInt32 TIME;


//对于COLOR不需要使用引用传递(因为COLOR本身才4字节==1个指针)
typedef struct _COLOR
{
        UByte r,g,b;
        Bool operator ==(_COLOR color)
        {
                if(r!=color.r)return False;
                if(g!=color.g)return False;
                if(b!=color.b)return False;
                return True;
        }
private:
        UByte unused; //内存对齐
}COLOR;

inline COLOR Rgb(UByte r,UByte g,UByte b)
{
        COLOR ret;
        ret.r=r;
        ret.g=g;
        ret.b=b;
        return ret;
}


}// end of namespace inst


#endif

362

主题

3023

帖子

3553

积分

论坛元老

Rank: 8Rank: 8

积分
3553
 楼主| 发表于 2008-1-14 03:08:00 | 显示全部楼层

Re:[2.0版]回调类中动态成员

//instList.h
#ifndef INST_LIST_H
#define INST_LIST_H
//common

#include <instTypes.h>
#include <instDefines.h>

///////////////////////////////////////////////////////////
namespace inst
{


template <class T> class IList
{
public:
        virtual void Add(T item)=0;
        virtual void Remove(Int32 index)=0;
        virtual void Clear()=0;
        virtual Int32 GetCount()const=0;
        virtual T Get(Int32 index)=0;
        virtual void Set(Int32 index,T val)=0;
        virtual Int32 Find(T val)=0;
        virtual void Insert(Int32 index,T val)=0;
        virtual ~IList(){};
};
/////////////////////////////////////////////////////////////////////////////
// note: Int32 a[3] is : a[0],a[1],a[2]! so,a[0 to 3] will be "Int32 a[3+1]"!
template <class T> class ArrayedList : public IList<T>
{
public:
        virtual void Add(T item);
        virtual void Remove(Int32 index);
        virtual void Clear();
        virtual Int32 GetCount()const{return m_Count;};
        void SetCount(Int32 count);
        virtual T Get(Int32 index){if(index>0&&index<=m_Count)return m_pTs[index];return 0;};
        virtual void Set(Int32 index,T val){if(index>0&&index<=m_Count)m_pTs[index]=val;};       
        virtual Int32 Find(T val);
        virtual void Insert(Int32 index,T val);
        virtual ~ArrayedList();
        ArrayedList();
private:
        T* m_pTs;
        Int32 m_Count;
};

template <class T> void ArrayedList<T>::SetCount(Int32 count)
{
        if(count==m_Count)return;
        T* tmp=new T[count+1]; tmp[0]=0;
        Int32 i;
        for(i=1;i<=MIN(count,m_Count);i++)
                tmp=m_pTs;
        if(count>m_Count)
        {
                for(i=m_Count;i<=count;i++)
                        tmp=0;
        }
        SafeDelArray(m_pTs);
        m_pTs=tmp;
        m_Count=count;
}

template <class T> ArrayedList<T>::ArrayedList()
{
        m_pTs=new T[1];
        m_pTs[0]=0;
        m_Count=0;
}
template <class T> ArrayedList<T>::~ArrayedList()
{
        SafeDelArray(m_pTs);
        m_Count=0;
}
template <class T> void ArrayedList<T>::Add(T item)
{
        T* tmp=new T[m_Count+1+1];  tmp[0]=0;
        for (Int32 i=1;i<=m_Count;i++)
                tmp=m_pTs;
        SafeDelArray(m_pTs);
        m_pTs=tmp;
        m_pTs[m_Count+1]=item;
        m_Count+=1;
}
template <class T> void ArrayedList<T>::Clear()
{
        SafeDelArray(m_pTs);
        m_pTs=new T[0];
}
template <class T> void ArrayedList<T>::Remove(Int32 index)
{
        T* tmp=new T[m_Count/* -1+1 */];  tmp[0]=0;
        Int32 i;
        for (i=1;i<=index-1;i++)
                tmp=m_pTs;
        if (index<m_Count)
                for (i=index+1;i<=m_Count;i++)
                        tmp[i-1]=m_pTs;
        m_Count-=1;
        SafeDelArray(m_pTs);
        m_pTs=tmp;
}

template <class T> Int32 ArrayedList<T>::Find(T val)
{
        if(m_Count<=0)return 0;
        for(Int32 i=1;i<=m_Count;i++)
                if(m_pTs==val)return i;
        return 0;
}
template <class T> void ArrayedList<T>::Insert(Int32 index,T val)
{
        return;
}

//////////////////////////////////////////////////////////////////

template <class T> class SList;
template <class T> class SNode
{
        friend class SList<T>;
private:
        T m_Val;
        SNode<T> *m_pNext;
};

template <class T> class SList:public IList<T>
{
public:
        virtual void Add(T item);
        virtual void Remove(Int32 index);
        virtual void Clear();
        virtual Int32 GetCount()const{        return m_Count;        };
        virtual T Get(Int32 index);
        virtual void Set(Int32 index,T val);
public:
        virtual Int32 Find(T val){ return 0; };
        virtual void Insert(Int32 index,T val){};
        virtual ~SList(){};
        SList();
private:
        Int32 m_Count;
        SNode<T> *m_pFirst,*m_pEnd;
};

template <class T> SList<T>::SList()
{
        m_Count=0;
        m_pFirst=null;
        m_pEnd=null;
}

template <class T> void SList<T>::Add(T item)
{
        SNode<T> *tmp=new SNode<T>;
        tmp->m_Val=item;
        tmp->m_pNext=null;

        if(m_Count>0)
                m_pEnd->m_pNext=tmp;
        else
                m_pFirst=tmp;
        m_pEnd=tmp;

        m_Count++;
}

template <class T> void SList<T>::Remove(Int32 index)
{
        if(index<=0||index>m_Count)return;
        Int32 i;

        SNode<T> *tmp=null;

        if(index==1)
        {
                tmp=m_pFirst;
                m_pFirst=m_pFirst->m_pNext;
                if(m_pFirst==null)m_pEnd=null;
                SAFEDEL(tmp);
        }
        else if(index==2)
        {
                tmp=m_pFirst->m_pNext;
                m_pFirst->m_pNext = m_pFirst->m_pNext->m_pNext;
                if(m_pFirst->m_pNext==null)m_pEnd=m_pFirst;
                SAFEDEL(tmp);
        }
        else
        {
                tmp=m_pFirst;
                for(i=1;i<=index-2;i++)
                        tmp=tmp->m_pNext;
                tmp->m_pNext = tmp->m_pNext->m_pNext;
                if(index==m_Count)m_pEnd=tmp;
                SAFEDEL(tmp); //这是在Add的时候创建的SNode
        }
/* also can :
        SNode<T> **pp;

        if(index==1)
        {
                pp = &(m_pFirst->m_pNext);
        }
        else
        {
                pp=&m_pFirst;
                for(i=1;i<=index-1;i++)
                        pp = &( (*pp)->m_pNext );
        }

        *pp = (*pp)->m_pNext;
        if(index==m_Count)m_pEnd = *pp;
*/
        m_Count--;
}

template <class T> void SList<T>::Clear()
{
        if(!m_pFirst)return;
        SNode<T> *tmp1,*tmp2;
        tmp1=m_pFirst;
        do
        {
                tmp2=tmp1->m_pNext;
                delete tmp1;
                tmp1=tmp2;
        }while(tmp2);

        m_Count=0;
}

template <class T> T SList<T>::Get(Int32 index)
{
        if(index<=0||index>m_Count)return 0;
        Int32 i;
        if(index==1)return m_pFirst->m_Val;
        if(index==m_Count)return m_pEnd->m_Val;
        SNode<T> *tmp;
        tmp=m_pFirst;
        for(i=1;i<=index-1;i++)
                tmp=tmp->m_pNext;
        return tmp->m_Val;
}

template <class T> void SList<T>::Set(Int32 index,T val)
{
        if(index<=0||index>m_Count)return;
        Int32 i;
        if(index==1){m_pFirst->m_Val=val;return;}
        if(index==m_Count){m_pEnd->m_Val=val;return;}
        SNode<T> *tmp;
        tmp=m_pFirst;
        for(i=1;i<=index-1;i++)
                tmp=tmp->m_pNext;
        tmp->m_Val=val;
}


}// end of namespace inst

#endif//INST_LIST_H

6

主题

60

帖子

64

积分

注册会员

Rank: 2

积分
64
发表于 2008-1-14 14:40:00 | 显示全部楼层

Re:[2.0版]回调类中动态成员

然后
omf = (void(__obj:: *)(void)) &CMyClass::Func()
就出错。所以只有用汇编!


这个可以用union_cast搞定麻..

362

主题

3023

帖子

3553

积分

论坛元老

Rank: 8Rank: 8

积分
3553
 楼主| 发表于 2008-1-14 18:02:00 | 显示全部楼层

Re: Re:[2.0版]回调类中动态成员

ybt631: Re:[2.0版]回调类中动态成员

然后
omf = (void(__obj:: *)(void)) &CMyClass::Func()
就出错。所以只有用汇编!


这个可以用union_cast搞定麻..



多谢您的指教!
下跪中!
大人万岁!


就是不知道怎么cast.

362

主题

3023

帖子

3553

积分

论坛元老

Rank: 8Rank: 8

积分
3553
 楼主| 发表于 2008-2-11 19:20:00 | 显示全部楼层

Re:[2.0版]回调类中动态成员

声明事件的例子:
DeclareEvent(Click,(CBtn*));
DeclareEvent(MouseDown,(IElement*,PARAM1,PARAM2,POS,POS));

添加事件回调函数的例子:
btnOK->Click.AddCallBack(this,&CForm2::btnOK_Click);


说明:今天又更新了一下,以前的话。。。添加回调很麻烦:
AddCallBack(btnOK->Click,CForm2,this,btnOK_Click,(CBtn*));


为什么今天能这么简单呢?
因为,模板函数,可以自动识别类型,而不需要显式地写出来。
这么一来就很爽了~~
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-12-20 04:36

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表