C#委托
C# 中的委托(Delegate)定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用if-else(switch)语句,同时使得程序具有更好的可扩展性。委托特别用于实现事件和回调方法。所有的委托都派生自 System.Delegate 类。
声明委托
委托声明决定了可由该委托引用的方法。委托可指向一个与其具有相同标签的方法。
语法
修饰符 delegate 返回值类型 委托名 ( 参数列表 );
delegate void IntMethodInvoker(intx);
定义了一个委托叫做 IntMethodInvoker ,这个委托可以指向带有一个int类型的参数,并且返回值是void的一个方法。
定义一个委托要定义方法的参数和返回值,使用delegate定义delegate void FirstInvoke(int x);
实例化委托
在定义好委托后就可以实例化委托,命名方法委托在实例化委托时必须带入方法的具体名称或者是null。
委托名 委托对象名 = new 委托名 ( 方法名 );
委托数组
委托名[] 委托对象名 = {委托的方法1,......};
委托做完函数的参数
访问类型 static 返回类型 方法名(委托类型 委托参数,参数.....)
多播委托
委托可以包含多个方法,这种委托叫做多播委托。使用多播委托就可以按照顺序调用多个方法,多播委托只能得到调用的最后一个方法的结果,一般我们把多播委托的返回类型声明为void。
Action action1 = Test1;
action2 += Test2;
action2 -= Test1
//获取委托列表
Delegate[] delegate = action1.GetInvocationList();
匿名方法
不用去定义一个方法,而是在后面直接使用匿名的方法。相当于直接把要引用的方法直接写在了后面,优点是减少了要编写的代码,减少代码的复杂性。
Func<T> 委托对象名 = delegate(方法参数){
方法体
};
事件
事件(Event)是类或者对象向其他类或对象通知发送的事情的一种特殊签名的委托
事件的声明
public event 委托类型 事件名;
事件使用event关键词来声明,他的返回值是一个委托类型
通常事件的命名,以名字+Event 作为他的名称,在编码中尽量使用规范命名,增加代码可读性。
示例代码:
using System;
delegate int NumberChanger(int n);
namespace DelegateAppl
{
class TestDelegate
{
static int num = 10;
public static int AddNum(int p)
{
num += p;
return num;
}
public static int MultNum(int q)
{
num *= q;
return num;
}
public static int getNum()
{
return num;
}
static void Main(string[] args)
{
// 创建委托实例
NumberChanger nc1 = new NumberChanger(AddNum);
NumberChanger nc2 = new NumberChanger(MultNum);
// 使用委托对象调用方法
nc1(25);
Console.WriteLine("Value of Num: {0}", getNum());
nc2(5);
Console.WriteLine("Value of Num: {0}", getNum());
Console.ReadKey();
}
}
}
C++ 委托实现
委托实际上就是将任意个同类型的函数交给一个对象(委托对象)来实现,可以想到如果要用C++来实现的话,肯定要用到函数指针。又因为非静态成员对象的调用依赖于具体的实例对象,为了能够以统一的方式存储这些函数指针就需要用多态进行封装。以下代码是利用C++特性实现的委托。
#include <iostream>
#include <list>
using namespace std;
class IDelegate
{
public:
virtual ~IDelegate() {}
virtual bool isType(const std::type_info &_type) = 0;
virtual void invoke() = 0; // 回调函数
virtual bool compare(IDelegate *_delegate) const = 0;
};
// 全局函数委托类
class CStaticDelegate : public IDelegate
{
public:
typedef void (*Func)(); // Func是函数指针类型的别名
CStaticDelegate(Func _func) : mFunc(_func) {}
// 查看类是否一致
virtual bool isType(const std::type_info &_type) { return typeid(CStaticDelegate) == _type; }
virtual void invoke() { mFunc(); } // 通过函数指针调用全局函数
// 输入委托基类
virtual bool compare(IDelegate *_delegate) const
{
// 判断和自身的类型是否相同
if (0 == _delegate || !_delegate->isType(typeid(CStaticDelegate)))
return false;
// 向下转型,判断函数地址是否相同
CStaticDelegate *cast = static_cast<CStaticDelegate *>(_delegate);
return cast->mFunc == mFunc;
}
private:
Func mFunc; // 定义私有函数指针
};
// 成员函数委托类
template <class T> // 对于成员函数委托,需要使用模版,因为不能对一个类单独化。
class CMethodDelegate : public IDelegate
{
public:
typedef void (T::*Method)(); // 这是一个指向 T作用域下的无返回值的无参成员函数 的函数指针
CMethodDelegate(T *_object, Method _method) : mObject(_object), mMethod(_method) {}
virtual bool isType(const std::type_info &_type) { return typeid(CMethodDelegate<T>) == _type; }
virtual void invoke()
{
(mObject->*mMethod)();
}
virtual bool compare(IDelegate *_delegate) const
{
if (0 == _delegate || !_delegate->isType(typeid(CMethodDelegate<T>)))
return false;
CMethodDelegate<T> *cast = static_cast<CMethodDelegate<T> *>(_delegate);
return cast->mObject == mObject && cast->mMethod == mMethod;
}
private:
T *mObject; // 定义调用这个函数的类对象指针,因为调用成员函数需要类对象来调用
Method mMethod; // 定义函数指针
};
// 委托管理
#if 1
class CMultiDelegate
{
public:
// 存储委托容器
typedef list<IDelegate *> ListDelegate;
// 容器迭代器
typedef ListDelegate::iterator ListDelegateIterator;
// 容器const迭代器
typedef ListDelegate::const_iterator ConstListDelegateIterator;
CMultiDelegate() {}
~CMultiDelegate() { clear(); }
// 是否为空
bool empty() const
{
for (ConstListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
{
if (*iter)
return false;
}
return true;
}
// 清空
void clear()
{
for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
{
if (*iter)
{
delete (*iter);
(*iter) = 0;
}
}
}
// 添加绑定
CMultiDelegate &operator+=(IDelegate *_delegate)
{
for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
{
if ((*iter) && (*iter)->compare(_delegate)) // 判断是否已经存在,就不在添加
{
delete _delegate;
return *this;
}
}
mListDelegates.push_back(_delegate);
return *this;
}
// 解开绑定
CMultiDelegate &operator-=(IDelegate *_delegate)
{
for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
{
if ((*iter) && (*iter)->compare(_delegate))
{
if ((*iter) != _delegate)
delete (*iter);
(*iter) = 0;
break;
}
}
delete _delegate;
return *this;
}
void operator()()
{
// 调用
ListDelegateIterator iter = mListDelegates.begin();
while (iter != mListDelegates.end())
{
if (0 == (*iter))
{
iter = mListDelegates.erase(iter);
}
else
{
(*iter)->invoke();
++iter;
}
}
}
private:
ListDelegate mListDelegates; // 链表容器
};
#endif
// 统一创建委托对象的回调函数
// 通过不同的函数重载,可以返回对应的委托
inline IDelegate *newDelegate(void (*_func)())
{
return new CStaticDelegate(_func);
}
template <class T>
inline IDelegate *newDelegate(T *_object, void (T::*_method)())
{
return new CMethodDelegate<T>(_object, _method);
}
// 测试
class TestClass
{
public:
static void print_static()
{
cout << "静态函数" << endl;
}
void print()
{
cout << "成员函数" << endl;
}
};
void print()
{
cout << "全局函数" << endl;
}
int main()
{
CMultiDelegate delegate;
TestClass c;
delegate += newDelegate(print);
delegate += newDelegate(&TestClass::print_static); // 静态函数
delegate += newDelegate(&c, &TestClass::print); // 普通成员函数,对象调用
delegate();
return 0;
}
C语言回调函数
C语言的回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。
#include <stdio.h>
void printWelcome(int len)
{
printf("欢迎%d\n", len);
}
void printGoodbye(int len)
{
printf("送客%d\n", len);
}
void callback(int times, void (*print)(int))
{
int i;
for (i = 0; i < times; ++i)
{
print(i); // 调用第二个参数对应的函数
}
}
void main(void)
{
callback(1, printWelcome);//欢迎0
callback(2, printGoodbye);//送客0 送客1
printWelcome(2);//欢迎2
}
typedef的作用:一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明,结合typedef可以简化回调函数类型声明。
#include <stdio.h>
typedef void (*print)();
void callback(print fun)
{
fun();
}
void printWelcome()
{
printf("欢迎\n");
}
void main(void)
{
callback(printWelcome);//欢迎
}