最近开始写了一些c#的东西,有个delegate的东西蛮有意思。
比如如下C#代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CSharpConsole
{
public delegate int Test(string str);
public class DelegaeFunc
{
public static int func1(string str)
{
Console.WriteLine("Func1" + str);
return 1;
}
public static int func2(string str)
{
Console.WriteLine("Func2" + str);
return 2;
}
}
class Program
{
public static int func3(string str)
{
Console.WriteLine("Func3" + str);
return 3;
}
static void Main(string[] args)
{
Test printHandler = new Test(func3);
printHandler += DelegaeFunc.func2;
printHandler += DelegaeFunc.func1;
int res = printHandler("hanliangwei");
Console.WriteLine(res);
Console.ReadKey();
}
}
}
程序会依次执行func3,func2,func1,最终返回值是func1的返回值。有点儿类似于事件绑定的意思。不过单纯的这种方式应该是不能绑定非静态成员函数的,winform里封装得EventHandler似乎可以?初学刚用,记不太清了。下面给出c++的模拟实现。
c++模拟的版本可支持普通函数与成员函数,主要是用模板来指定返回值与类。对于函数参数定为只有一个void *类型。因为对于多个自定义的参数,我除了多定义几个类,其他好像也没有想到一个好的办法。而且想着win32sdk中不是很多都是这么做的嘛。void*其实可以做很多事儿了。忽然想到应该用两个void*的,这样可能更灵活一点?
具体实现:
对于普通函数,其实很简单,只要定义好函数指针,再定义一个list,保存下来每个函数指针即可,而对于类,需要保存它的成员函数地址以及调用它的那个对象,由于是同一个类中,所以对于Delegate的类模板只能有一个模板参数,就是返回值,那对于成员函数类型的就应该在添加函数上做一个模板函数来萃取出这个类对象的类型,那这时候list该怎么定义?所以需要一个类来辅助,辅助存储类对象与成员函数指针,所以这个辅助类应该有两个模板参数,class_type 与 return_type,但是有一个问题,在存储于Delegate类中的这个list没法给出class_type怎么办,所以还需要给辅助类加一个基类,这样在list中就存储基类的指针,添加的时候添加的是派生类的对象,利用多态进行执行代理的成员函数。
(此方法借鉴了一点一个叫sigslot的库,是c++写的一个模仿qt的信号槽库)
所以代码如下
#include <iostream>
#include<list>
using namespace std;
template<typename Return_Type>
class ClassProxyBase
{
public:
virtual Return_Type Execute(void * p) { return 0; }
};
template<typename ClassType, typename Return_Type>
class ClassProxy:public ClassProxyBase<Return_Type>
{
public:
typedef Return_Type(ClassType::*PMemFunc)(void *p);
ClassProxy(ClassType* pObj, PMemFunc memFunc) :m_pObj(pObj), m_lpfnMemfunc(memFunc) {}
Return_Type Execute(void * p)
{
return (m_pObj->*m_lpfnMemfunc)(p);
}
private:
ClassType *m_pObj;
PMemFunc m_lpfnMemfunc;
};
template<typename Return_Type>
class Delegate
{
public:
Delegate() {}
~Delegate()
{
for (auto & lpfn : m_listMemberFuncPointers)
{
delete lpfn;
}
}
typedef Return_Type(*PFUNC)(void *);
Return_Type operator()(void * p)
{
Return_Type returnValue;
for (auto & lpfn : m_listFunctionPointers)
{
returnValue = (*lpfn)(p);
}
for (auto & lpfn : m_listMemberFuncPointers)
{
returnValue = lpfn->Execute(p);
}
return returnValue;
}
Return_Type operator =(PFUNC ptr)
{
if (ptr == NULL)
return;
m_listFunctionPointers.clear();
m_listFunctionPointers.push_back(ptr);
}
void operator += (PFUNC ptr)
{
m_listFunctionPointers.push_back(ptr);
}
private:
list<PFUNC> m_listFunctionPointers;
//下面是为了支持类的成员函数
public:
template<class ClassType>
void Add(ClassType * pObj, Return_Type(ClassType::*pMemfunc)(void *p))
{
ClassProxy<ClassType,Return_Type> *obj = new ClassProxy<ClassType, Return_Type>(pObj, pMemfunc);
m_listMemberFuncPointers.push_back(obj);
}
private:
list<ClassProxyBase<Return_Type>*>m_listMemberFuncPointers;
};
class Test
{
public:
int test(void * p)
{
cout << "class Test:" << *(int*)p << endl;
return 30;
}
};
int func1(void *p)
{
int * ptr = (int *)p;
cout << "func1:" << *(int*)p<<endl;
*ptr = 20;
return 1;
}
int func2(void *p)
{
cout << "func2:" << *(int*)p<<endl;
return 2;
}
int main()
{
Delegate<int> delegateObj;
delegateObj += func1;
delegateObj += func2;
Test obj;
delegateObj.Add(&obj,&Test::test);
int t = 10;
int res = delegateObj((void*)&t);
cout << "res:" << res << endl;
system("pause");
}
执行结果如下:
func1:10
func2:20
class Test:20
res:30