首页
社区
课程
招聘
[原创]VC++中委托的简单实现(源代码)
2010-1-11 02:12 15775

[原创]VC++中委托的简单实现(源代码)

2010-1-11 02:12
15775
在C#中的委托(deletegate)极大地增强了语言的功能,以下代码是在VC++中的简单实现.欢迎交流.
参考资料:http://blog.csdn.net/chenjiazhou/relatedarticles/470323.aspx

// vc++ compile: cl /nologo /MD DelegateTest.cpp

#include <stdio.h>
#pragma runtime_checks( "s", off )    // 由于使用内联汇编,当启用堆栈帧运行时错误检查会产生错误

#pragma pack(push, 4)
struct Delegate
{
public:
    Delegate(){ pObj = 0; pFunc = 0; }
  
    void Bind(void (*pFunction)(void*)){ Bind(0, pFunction); }
    void Bind(void *pobj, void *pF){ pObj = pobj; pFunc = pF; }

    int operator==(Delegate& d) const
    { return (pObj == d.pObj) && (pFunc == d.pFunc); }

public:
    void Invoke(void*);

protected:
    void* pObj;
    void* pFunc;
};
#pragma pack(pop)

__declspec(naked) 
void Delegate::Invoke(void* p)  // key code
{
    __asm
    {
        mov eax, ecx
        mov ecx, dword ptr [eax+0]  ; pObj
        jmp dword ptr [eax+4]       ; pFunc
    }
}

inline Delegate CreateDelegate(void (*pFunction)(void*))
{ Delegate d; d.Bind(0, pFunction); return d; }

#define DELEGATE(ClassName)  \
inline Delegate CreateDelegate(ClassName *pobj, void (ClassName::*pFunction)(void*)) \
{ union { void* pF; void (ClassName::*pTmp)(void*); } u; u.pTmp = pFunction; Delegate d; d.Bind(pobj, u.pF); return d; }\

class MulticastDelegate
{
private:
    struct DelegateNode
    {
        DelegateNode(){ hander.Bind(0,0); pNext = 0; }
        ~DelegateNode(){ hander.Bind(0,0); pNext = 0; }
    
        Delegate hander;
        DelegateNode* pNext;
    };

public:
    MulticastDelegate()
    {
        pHead = 0;
    }
    ~MulticastDelegate()
    {
        DelegateNode* p = pHead;
        while(p != 0)
        {
            DelegateNode* pnext = p->pNext;
            delete p;
            p = pnext;
        }
        pHead = 0;
    }

    void AddDelegate(Delegate d)
    {
        DelegateNode* pNew = new DelegateNode;
        pNew->hander = d;
        pNew->pNext = pHead;
        pHead = pNew;
    }
    void operator+=(Delegate d)
    { AddDelegate(d); }

    void RemoveDelegate(Delegate d)
    {
        if(pHead == 0)
        return;

        if(pHead->hander == d)
        {
        DelegateNode* p = pHead->pNext;
        delete pHead;
        pHead = p;
        return;
        }

        DelegateNode *pLast, *pCur;
        pLast = pHead;
        pCur = pLast->pNext;
        while(pCur != 0)
        {
            if(pCur->hander == d)
            {
                DelegateNode* tmp = pCur ->pNext;
                delete pCur;
                pLast->pNext = tmp;
                break;
            }  
            else
            {
                pLast = pCur;
                pCur = pCur->pNext;
            }
        }
    }
    void operator-=(Delegate d)
    { RemoveDelegate(d); }

    void Invoke(void* param)
    {
        DelegateNode* p = pHead;
        while(p != 0)
        {
            p->hander.Invoke(param);
            p = p->pNext;
        }
    }

private:
    DelegateNode *pHead;
};

class A
{
public:
    void Func1(void* p){ printf("A::Func1(%d)\n", *(int*)p); }
};
DELEGATE(A)

class B
{
public:
    void Func1(void* p){ printf("B::Func1(%d)\n", *(int*)p); }
};
DELEGATE(B)

void Demo(void* p){ printf("Demo(%d)\n", *(int*)p); }

int main(int argc, char *argv[])
{
    A a;
    B b;
    int param = 0;

    printf("Test single delegate...\n");

    Delegate x[3];
    x[0] = CreateDelegate(&a, &A::Func1);
    param++;
    x[0].Invoke(¶m);
    x[1] = CreateDelegate(&b, &B::Func1);
    param++;
    x[1].Invoke(¶m);
    x[2].Bind(Demo);
    param++;
    x[2].Invoke(¶m);

    printf("\nTest multicast delegate...\n");
    MulticastDelegate md;
    md += CreateDelegate(&a, &A::Func1);
    md += CreateDelegate(&b, &B::Func1);
    md += CreateDelegate(Demo);
    md.Invoke(¶m);

    printf("\nTest remove delegate...\n");

    md -= CreateDelegate(&b, &B::Func1);
    md.Invoke(¶m);

    printf("\nTest OK!\n");
    return 0;
}

/* output:
R:\>cl /nologo /MD Delegate.cpp
Delegate.cpp

R:\>delegate
Test single delegate...
A::Func1(1)
B::Func1(2)
Demo(3)

Test multicast delegate...
Demo(3)
B::Func1(3)
A::Func1(3)

Test remove delegate...
Demo(3)
A::Func1(3)

Test OK!
*/


[培训]《安卓高级研修班(网课)》月薪三万计划

收藏
点赞6
打赏
分享
最新回复 (3)
雪    币: 63
活跃值: (17)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
nevergone 3 2010-1-11 09:17
2
0
不需要用汇编写
没有可移植性
要template可以实现
雪    币: 214
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
colboy 2010-1-28 07:57
3
0
boost做得挺好了..
雪    币: 634
活跃值: (174)
能力值: ( LV9,RANK:260 )
在线值:
发帖
回帖
粉丝
Fypher 4 2010-1-28 10:26
4
0
委托不过是C#为了遵守没有指针的承诺但是又不得不提供函数指针,于是自圆其说地诞生出的一种扭曲的函数指针。
C/C++没那么碍手碍脚,不需要这种东西。
游客
登录 | 注册 方可回帖
返回