引言
在.NET中,委托被用来实现事件处理。它答应一个类(方法)先注册一个事件,然后当此事件被引发时此注册的方法就会被调用。在非.Net环境的C++中,这并不是一件轻易的事,尤其是类的非静态成员函数,要做为回调函数就更困难了。本文的目标就是给出一种解决方案,使类的静态成员函数,非静态成员函数,还有类非成员函数都能像回调函数一样使用。这个实现非常重视类型安全,为了保持类型安全我们省去了某些特性的实现。
什么是委托?
.NET框架中对委托的定义如下:
"委托是一个可以保持对某个方法引用的类。不同于其它类,委托类有自己的签名(返回值,参数类型,个数),并且只能引用与其签名匹配的方法。委托其实可以看成一个类型安全的函数指针或回调函数。
一个提供了委托的类答应其它函数或类在此委托上注册事件处理函数。然后当这个类的委托被执行时,就会遍历其处理函数列表,逐个调用,并传入传给委托的信息。而提供委托的那个类不需要知道委托注册了多少处理函数,委托自己会处理这一切。
正文
函数对象(functor)概述
我们用函数对象(functor, function object)来实现C++中的委托。这答应一个非静态成员函数能在特定对象的环境中被调用。我们用模板技术来保证任何类类型都能在其上使用。一个基本的函数对象(functor)定义如下:
template<class T>
class Functor
{
public:
// ConstrUCtor takes the values and stores them
Functor(T *pObj, int (T::*pFunc)(int))
{
m_pObject = pObj;
m_pFunction = pFunc;
}
// Invokes the stored function
intoperator ()(int p)
{
return (m_pObject->*m_pFunction)(p);
}
private:
T *m_pObject; // Pointer to the object
int (T::*m_pFunction)(int); // Pointer to the function
};
这个函数对象(functor)使用的函数格式为:返回类型为int,带一个类型为int的参数。操作符operator ()是函数对象的要害。它使一个函数对象(functor)使用起来和函数调用一样。它的工作就是每次执行时调用保存在类内部的函数指针。以下代码展示了如何使用这个函数对象(functor):
class MyClass
{
public:
int Square(int p) { return p * p; };
};
void some_function()
{
// Create a class to call in the context of
MyClass theClass;
// Create and initialise the functor object
Functor<MyClass> myFunc(&theClass, MyClass::Square);
// Call the functor using the overloaded () operator
int result = myFunc(5);
// result will hold the value 25
}
由于重载了operator ()运算符,调用函数对象(functor)几乎就和调用该函数本身一样方便。这里说“几乎”是因为指向实际对象的指针并没有被显示使用-它被存放在函数对象(functor)内部使用。
的确,这很不错,但是我们为什么要使用函数对象(functor),而不是函数本身呢?很好的问题,当你知道你要调用的函数的签名(返回值和参数)而不关心其是否是类的成员函数,是哪个类的成员函数时,函数对象就非常的有用(译注:将这一信息局部化在对象内部,从而以统一的方式来调用所有具有相同签名的函数)看以下代码,我将它们划分成几项以便理解:
首先,是一个用纯虚基类来表示的一个以一个int为参数,返回值为int的函数对象。它只有一个函数,虚拟的operator()操作符,这样,我们就可以在不知道某函数对象实例的实际对象类型的情况下调用函数对象(functor)了.
// Abstract base class
class Functor
{
public:
// Invoke the functor (no implementation here as it must be overridden)
virtualintoperator()(int) = 0;
};
下面就是一个可以被实例化为任何类类型的模板类,假设它也有一个以一个int为参数,返回为int的函数。它是从Functor派生来的,所以一个指向特定函数对象的指针可以传给任何一个需要其基类对象(Functor)指针的地方,所以此函数对象可以不管其真正的对象类型而被调用。除了基类和类名,这个类与之前给出的类是完全一样的:
// Template functor
template<class T>
class TemplateFunctor : public Functor
{
public:
// Constructor takes the values and stores them
TemplateFunctor(T *pObj, int (T::*pFunc)(int))
{
m_pObject = pObj;
m_pFunction = pFunc;
}
// Invokes the stored function (overrides Functor::operator ())
intoperator ()(int p)
{
return (m_pObject->*m_pFunction)(p);
}
private:
T *m_pObject; // Pointer to the object
int (T::*m_pFunction)(int); // Pointer to the function
};
下面是一个以函数对象指针和该函数的参数为参数的简单函数,用来调用该函数对象。注重这里以基类Functor指针而不是派生模板类指针为参数。这是必需的,因为每一个不同的模板参数产生的模板类都是不同的类型,直接用此模板类为参数就不能支持多种类型了。
int OperateOnFunctor(int i, Functor *pFunc)
{
if(pFunc)
return (*pFunc)(i);
else
return0;
}
这是一个简单的类,它包含了一个符合函数对象要求的函数-以一个int为参数并返回一个int。注重此函数还用到了一个该类的数据成员,这说明这个回调函数实际应该是在实例对象的环境下被执行的,所以引用同一类不同对象的函数对象会产生不同的结果:
class ClassA
{
public:
ClassA(int i) { m_Value = i; }
int FuncA(int i)
{
return (m_Value - i);
}
int m_Value;
};
这是一个简单的程序,它创建两个引用同一类类型的函数对象的实例,针对两个同类型的不同的对象实例调用函数对象,并显示结果.
int main()
{
ClassA a(20);
ClassA b(10);
TemplateFunctor<ClassA> functorA(&a, ClassA::FuncA);
TemplateFunctor<ClassA> functorB(&b, ClassA::FuncA);
cout << "a gives the value " << OperateOnFunctor(5, &functorA) << endl;
cout << "b gives the value " << OperateOnFunctor(5, &functorB) << endl;
return0;
}
产生结果如下:
a gives the value 15
b gives the value 5
在这个例子中,两个函数对象都调用了ClassA::FuncA,但是针对不同的对象.一个相似但又有些不同的例子是针对不同的类调用函数对象,假设我们实现了一个ClassB如下:
class ClassB
{
public:
ClassB(int i) { m_Value = i; }
int FuncB(int i)
{
return (m_Value + i); // + instead of -
}
int m_Value;
};
假如我们的main函数实现如下,得到的结果就会有所不同:
int main()
{
ClassA a(20);
ClassB b(10);
TemplateFunctor<ClassA> functorA(&a, ClassA::FuncA);
TemplateFunctor<ClassB> functorB(&b, ClassB::FuncB);
cout << "a gives the value " << OperateOnFunctor(5, &functorA) << endl;
cout << "b gives the value " << OperateOnFunctor(5, &functorB) << endl;
return0;
}
结果如下:
a gives the value 15
b gives the value 15
这个例子中,functorB调用了ClassB::FuncB,因此结果是(10+5)。注重我们几乎用同样的方式把两个函数对象传给了OperateOnFunctor)。是基类Functor的设计提供了我们这种方便性。
用宏参数化函数对象
所以函数对象是非常方便的东西,但是假如我们需要不同的参数或返回类型,我们就不得不重写这些类,这比较头痛。幸好,我们可以利用宏的特性使这个变的简单。也许会有人说这样是过份使用宏,但这工作的很好,而且,在模板答应我们修改函数原型前,这是唯一的解决方案。
因此我们定义了以下宏:
Collapse
#define DECLARE_FUNCTOR(name, parmdecl, parmcall) /* A function object base class for this parameter list */ class name##Functor { public: virtualvoidoperator () parmdecl = 0; }; /* Template class derived from Functor for make class-specific function objects */ template<class C> class name##TFunctor : public name##Functor { public: /* Only constructor - stores the given data */ name##TFunctor(C* pObj, void (C::*pFunc)parmdecl) { m_pObj = pObj; m_pFunc = pFunc; } /* Invokes the function object with the given parameters */ voidoperator ()parmdecl { (m_pObj->*m_pFunc)parmcall; } C *m_pObj; /* Object pointer */ void (C::*m_pFunc)parmdecl; /* Method pointer */ };
3个宏参数的意义如下:
name -函数对象的名字。Functor基类会加上“Functor“的后缀,而模板类会加上”TFunctor“的后缀。
parmdecl -操作符operator()的参数列表声明.列表必须包括在小括号对里面
parmcall -传给内部函数的实参列表。以下例子可以很好的解释这两个列表的关系:
使用该宏的例子:
DECLARE_FUNCTOR(Add, (int p1, int p2), (p1, p2))
定义了一个以2个int为参数函数对象AddFunctor。宏展开后代码如下(当然,事实上它们应该在一行上,并且没有注释)
Collapse
/* A function object base class for this parameter list */
class AddFunctor
{
public:
virtualvoidoperator () (int p1, int p2) = 0;
};
/* Template class derived from AddFunctor for
make class-specific function objects */
template<class C>
class AddTFunctor : public AddFunctor
{
public:
/* Only constructor - stores the given data */
AddTFunctor(C* pObj, void (C::*pFunc)(int p1, int p2))
{
m_pObj = pObj;
m_pFunc = pFunc;
}
/* Invokes the function object with the given parameters */
voidoperator ()(int p1, int p2) { (m_pObj->*m_pFunc)(p1, p2); }
C *m_pObj; /* Object pointer */
void (C::*m_pFunc)(int p1, int p2); /* Method pointer */
};
正如你所看到的,在所有name出现的地方都被“Add“所代替,parmdecl则被(int P1, int p2)替换,而parmcall则被(p1, p2)替换)。为了更好的体现parmdecl和parmcall的关系,看以下operator()操作符,第一行是宏,第二行是展开后的代码:
voidoperator ()parmdecl { (m_pObj->*m_pFunc)parmcall; }
voidoperator ()(int p1, int p2) { (m_pObj->*m_pFunc)(p1, p2); }
parmdecl是函数参数列表的声明,而parmcall是函数调用时的实参.遗憾的是,我们没有办法用宏来自动生成这些.这种实现有些不是那么优雅, 但它可以很好的工作,并且保证了函数的类型安全
委托的实现
委托的实现类似于函数对象,但委托存储了一个函数对象的列表,当委托被调用时就会遍历调用这个列表中的函数对象,而不是只有一个函数对象。这意味着假如需要的话,我们可以存储,调用多个处理函数。类的定义如下(没有包括实现代码)。我没有加入functor的定义因为上面已经定义过了。函数对象实际上也会在这个宏当中定义,在这个名字空间中:
Collapse
#define DECLARE_DELEGATE(name, parmdecl, parmcall) namespace name##Delegate { class Delegate { public: Delegate(); ~Delegate(); /* Template function for adding member function callbacks */ template<class C> void Add(C *pObj, void (C::*pFunc)parmdecl); /* Add a non-member (or static member) callback function */ void Add(void (*pFunc)parmdecl); /* Template function for removing member function callbacks */ template<class C> void Remove(C *pObj, void (C::*pFunc)parmdecl); /* Removes a non-member (or static member) callback function */ void Remove(void (*pFunc)parmdecl); /* Addition operators */ voidoperator +=(Functor *pFunc); voidoperator +=(void (*pFunc)parmdecl); /* SuBTraction operators */ template<class C> voidoperator -=(TFunctor<C> *pFunc); voidoperator -=(void (*pFunc)parmdecl); /* Calls all the callbacks in the callback list */ void Invoke parmdecl; /* Calls all the callbacks in the callback list */ voidoperator ()parmdecl; private: /* List of callback functions */ std::vector<Functor*> m_pFuncs; /* typedef'd iterator */ typedef std::vector<Functor*>::iterator vit; }; }
一些重点
委托和函数对象类都放在它们自己的名字空间中,所以它们是一个易治理的整体。
函数对象存在一个STL vector中。vector包含了指向基类Functor的指针,所以它可以包含任何类型的模板函数对象的实例。当然,还有一个函数对象没有被列出来,这是用来包装非类成成员函数或类的静态成员函数的。它们功能上大致相同,只是它不需要保存一个对象指针,或要求函数是类的一部份
我们有两种方法来调用委托的函数对象-Invoke函数或operator()操作符.两种方法的效果完全相同,实际上()操作符内部调用了Invoke来实现。
有两种方法从委托增加,删除回调函数.用Add()/Remove方法,或者用+=/-=运算符。同Invoke()/operator()一样,这两种方法在功能上相同-操作符直接调用非操作符方法。这两种方法均有两个重载,一个用来接收非静态类成员函数,一个用来接收非类成员函数或者类静态成员函数。
还有一个用来创建函数对象的非成员函数没有列出来,其创建出来的对象用来传给+=和-=操作符函数。此函数并没有被放在该类所在的名字空间中,其名字为传给宏DECLARE_DELEGATE的name加上“Handler“的后缀,例如:
DECLARE_DELEGATE(Add, (int p1, int p2), (p1, p2))
将会给出如下的函数原型:
template<class C>
AddDelegate::TFunctor<C> *AddHandler(C *pObj,
void (C::*pFunc)(int p1, int p2));
如何使用
展示如何使用这些代码的最好方法就是给出一个例子。以下例子定义了一个以int, float为参数的委托。并定义了两个简单的类和其相应函数,当然,也使用了一个静态成员函数与一个非成员函数
Collapse
DECLARE_DELEGATE(Add, (int p1, float p2), (p1, p2))
class A
{
public:
A() { value = 5; }
virtualvoid Fun1(int val, float val2)
{
value = val*2*(int)val2;
cout << "[A::Fun1] " << val << ", " << val2 << endl;
}
staticvoid StaticFunc(int val, float val2)
{
cout << "[A::StaticFunc] " << val << ", " << val2 << endl;
}
public:
int value;
};
class B : public A
{
public:
void Fun1(int val, float val2)
{
value += val*3*(int)val2;
cout << "[B::Fun1] " << val << ", " << val2 << endl;
}
};
void GlobalFunc(int val, float val2)
{
cout << "[GlobalFunc] " << val << ", " << val2 << endl;
}
int main()
{
// Create class instances
A a;
B b;
// Create an instance of the delegate
AddDelegate::Delegate del;
// Add our handlers
del += AddHandler(&a, A::Fun1); // or del.Add(&a, A::Fun1);
del += AddHandler(&b, B::Fun1); // or del.Add(&b, B::Fun2);
del += GlobalFunc; // or del.Add(GlobalFunc);
del += A::StaticFunc; // or del.Add(A::StaticFunc);
// Invoke the delegate
del(4, 5); // or del.Invoke(4, 5);
// Print the class values
cout << "[main] a.value = " << a.value << endl;
cout << "[main] b.value = " << b.value << endl;
// Remove some of the handlers
del -= AddHandler(&a, A::Fun1); // or del.Remove(&a, A::Fun1);
del -= A::StaticFunc; // or del.Remove(A::StaticFunc);
// Invoke the delegate again
del(4, 5); // or del.Invoke(4, 5);
// Print the class values
cout << "[main] a.value = " << a.value << endl;
cout << "[main] b.value = " << b.value << endl;
return0;
}
这个例子展示了委托几乎所有的操作,其结果如下:
[A::Fun1] 4, 5
[B::Fun1] 4, 5
[GlobalFunc] 4, 5
[A::StaticFunc] 4, 5
[main] a.value = 40
[main] a.value = 65
[B::Fun1] 4, 5
[GlobalFunc] 4, 5
[main] a.value = 40
[main] b.value = 125
代码用了stl.h文件(由Oskar Weiland编写)来去除编译stl时的警告信息,这个文件包含在zip文件中,当然也可以从这儿得到。可下载的代码包括delegate.h和以上给出的例子代码
QQread.com
推出Windows2003教程
win2003安装介绍
win2003网络优化
win2003使用技巧
win2003系统故障
服务器配置
专家答疑
更多的请看:http://www.qqread.com/windows/2003/index.Html类帮助
因为代码是由DECLARE_DELEGATE定制的,这里我用<parameters>来表示你传入的参数)
Method: template<class C> void Delegate::Add(C *pObj, void (C::*pFunc)(<parameters>))
Description: Adds a callback function that is a non-static member function of a class. The member function must return void and take a parameter list that is the same as <parameters>.
Return value: void - nothing.
Parameters: pObj - A pointer to the object to call the callback method in the context of.
pFunc - A pointer to the callback method to call.
Method: void Delegate::Add(void (*pFunc)(<parameters>))
Description: Adds a callback function that is either a static member function of a class or is not a class member function. The function must return void and take a parameter list that is the same as <parameters>.
Return value: void - nothing.
Parameters: pFunc - A pointer to the callback function to call.
Method: template<class C> void Delegate::Remove(C *pObj, void (C::*pFunc)parmdecl)
Description: Removes a callback function from the callback function list
Return value: void - nothing.
Parameters: pObj - A pointer to the object that is being referred to.
pFunc - A pointer to the callback method being referred to.
These two parameters together specify the callback handler to be removed.
Method: void Delegate::Remove(void (*pFunc)parmdecl)
Description: Removes a callback function from the callback function list
Return value: void - nothing.
Parameters: pFunc - A pointer to the callback method being referred to.
Method: void Delegate::operator +=(Functor *pFunc)
Description: Adds a callback function that is a non-static member function of a class. The member function must return void and take a parameter list that is the same as <parameters>.
Return value: void - nothing.
Parameters: pFunc - A pointer to the functor to call. This should be created using the <name>Handler() function.
Method: void Delegate::operator +=(void (*pFunc)(<parameters>))
Description: Adds a callback function that is either a static member function of a class or is not a class member function. The function must return void and take a parameter list that is the same as <parameters>.
Return value: void - nothing.
Parameters: pFunc - A pointer to the callback function to call.
Method: void Delegate::operator -=(Functor *pFunc)
Description: Removes a callback function that is a non-static member function of a class.
Return value: void - nothing.
Parameters: pFunc - A pointer to the functor to remove. This should be created using the <name>Handler() function, and is deleted by the function.
Method: void Delegate::operator -=(void (*pFunc)(<parameters>))
Description: Removes a callback function that is either a static member function of a class or is not a class member function.
Return Value: void - nothing.
Parameters: pFunc - A pointer to the callback function to remove.
Method: void Delegate::Invoke(<parameters>)
Description: Calls all the callbacks in the callback list with the specified parameters.
Return Value: void - nothing.
Parameters: <parameters> - The parameters to pass to the callback functions, as specified in the parameter to DECLARE_DELEGATE().
Method: void Delegate::operator ()(<parameters>)
Description: Calls all the callbacks in the callback list with the specified parameters
Return Value: void - nothing.
Parameters: <parameters> - The parameters to pass to the callback functions, as specified in the parameter to DECLARE_DELEGATE().
后续功能
增加一个宏-参数化的类来支持返回类型,为委托中每个函数对象存储返回值用以之后访问。
加一些支持固定参数个数的模板类,如只带一个参数的类,或只带两个参数的类等),这可能需要或不需要在量的类来实现-为委托的返回值或其它功能提供不同类型的类。
QQread.com
推出Windows2003教程
win2003安装介绍
win2003网络优化
win2003使用技巧
win2003系统故障
服务器配置
专家答疑
更多的请看:http://www.qqread.com/windows/2003/index.html建议?
History
版本信息
2003-8-19-初始版本
代码文件
///////////////////////////////////////////////////////////////////////////
// delegate.h
// Interface/implementation of the delegate classes and macros
///////////////////////////////////////////////////////////////////////////
// Author: Ryan Binns
// Changelog:
// 19-Aug-2003 : Initial Release
///////////////////////////////////////////////////////////////////////////
#ifndef DELEGATE_H__
#define DELEGATE_H__
// This STL include file removes the STL warning when the compiler
// is set to warning level 4. It was written by Oskar Wieland, and
// is available at:
// http://www.codeproject.com/vcpp/stl/stl_without_warnings.ASP
#define STL_USING_VECTOR
/*
* Here, for convenience, I just ignore this header file but put the code directly.
*/
//#include "stl.h"
#ifdef STL_USING_VECTOR
#pragma warning(push)
#include <yvals.h> // warning numbers get enabled in yvals.h
#pragma warning(disable: 4018) // signed/unsigned mismatch
#pragma warning(disable: 4100) // unreferenced formal parameter
#pragma warning(disable: 4245) // conversion from 'type1' to 'type2', signed/unsigned mismatch
#pragma warning(disable: 4663) // C++ language change: to eXPlicitly specialize class template 'vector'
#pragma warning(disable: 4702) // unreachable code
#pragma warning(disable: 4710) // 'function' : function not inlined
#pragma warning(disable: 4786) // identifier was truncated to 'number' characters in the debug information
#include <vector>
#pragma warning(pop)
#endif
// Declares a delegate
// name - gives the beginning of the name of the delegate namespace, so
// DECLARE_DELEGATE(Add, ..., ...) would make a namespace
// called "AddDelegate" which contains the Add delegate classes.
// parmdecl - is the declaration of the parameters in the callbacks
// (surrounded by brackets), such as "(int val1, int val2)"
// parmcall - is how the parameters are called (surrounded in brackets),
// such as "(var1, var2)"
// so: DECLARE_DELEGATE(Add, (int val1, int val2), (val1, val2))
// would declare a delegate called AddDelegate, that takes two int
// parameters (the parameter names are not important).
#define DECLARE_DELEGATE(name, parmdecl, parmcall)
namespace name##Delegate
{
class Delegate; /* Forward declaration */
/* A function object base class for this parameter list */
class Functor
{
public:
virtual void Invoke parmdecl = 0;
virtual bool isMethod() = 0;
virtual bool operator ==(Functor *pf) = 0;
};
/* Template class derived from Functor for
making class-specific function objects */
template<class C>
class TFunctor : public Functor
{
public:
/* Only constructor - stores the given data */
TFunctor(C* pObj, void (C::*pFunc)parmdecl)
{
m_pObj = pObj;
m_pFunc = pFunc;
}
bool isMethod() { return true; }
bool operator ==(Functor *pf)
{
if(!pf->isMethod())
return false;
TFunctor<C> *pf1 = (TFunctor<C>*)pf;
if((pf1->m_pObj == m_pObj) && (pf1->m_pFunc == m_pFunc))
return true;
else
return false;
}
/* Invokes the function object with the given parameters */
void Invoke parmdecl { (m_pObj->*m_pFunc)parmcall; }
private:
C *m_pObj; /* Object pointer */
void (C::*m_pFunc)parmdecl; /* Method pointer */
};
/* Class for function function objects */
class FFunctor : public Functor
{
public:
/* Only constructor - stores the given data */
FFunctor(void (*pFunc)parmdecl) { m_pFunc = pFunc; }
bool isMethod() { return false; }
bool operator ==(Functor *pf)
{
if(pf->isMethod())
return false;
FFunctor *pf1 = (FFunctor*)pf;
if(pf1->m_pFunc == m_pFunc)
return true;
else
return false;
}
/* Invokes the function object with the given parameters */
void Invoke parmdecl { m_pFunc parmcall; }
private:
void (*m_pFunc)parmdecl; /* Function pointer */
};
/* Delegate class definition */
class Delegate
{
public:
Delegate() { };
~Delegate()
{
for(vit i=m_pFuncs.begin(); i!=m_pFuncs.end(); i++)
delete (*i);
m_pFuncs.clear();
}
/* Template function for adding member function callbacks */
template<class C>
void Add(C *pObj, void (C::*pFunc)parmdecl)
{
m_pFuncs.push_back(new TFunctor<C>(pObj, pFunc));
}
/* Add a non-member (or static member) callback function */
void Add(void (*pFunc)parmdecl)
{
m_pFuncs.push_back(new FFunctor(pFunc));
}
/* Template function for removing member function callbacks */
template<class C>
void Remove(C *pObj, void (C::*pFunc)parmdecl)
{
TFunctor<C> f(pObj, pFunc);
for(vit i=m_pFuncs.begin(); i!=m_pFuncs.end(); i++)
{
if(*(*i) == &f)
{
delete *i;
m_pFuncs.erase(i);
break;
}
}
}
/* Removes a non-member (or static member) callback function */
void Remove(void (*pFunc)parmdecl)
{
FFunctor f(pFunc);
for(vit i=m_pFuncs.begin(); i!=m_pFuncs.end(); i++)
{
if(*(*i) == &f)
{
delete *i;
m_pFuncs.erase(i);
break;
}
}
}
/* Addition operators */
void operator +=(Functor *pFunc)
{
m_pFuncs.push_back(pFunc);
}
void operator +=(void (*pFunc)parmdecl)
{
m_pFuncs.push_back(new FFunctor(pFunc));
}
/* Subtraction operators */
void operator -=(Functor *pFunc)
{
for(vit i=m_pFuncs.begin(); i!=m_pFuncs.end(); i++)
{
if(*(*i) == pFunc)
{
delete *i;
m_pFuncs.erase(i);
break;
}
}
delete pFunc;
}
void operator -=(void (*pFunc)parmdecl)
{
Remove(pFunc);
}
/* Calls all the callbacks in the callback list */
void Invoke parmdecl
{
for(vit i=m_pFuncs.begin(); i!=m_pFuncs.end(); i++)
(*i)->Invoke parmcall;
}
/* Calls all the callbacks in the callback list */
void operator ()parmdecl { Invoke parmcall; }
private:
/* List of callback functions */
std::vector<Functor*> m_pFuncs;
/* typedef'd iterator */
typedef std::vector<Functor*>::iterator vit;
};
}
template<class C>
name##Delegate::TFunctor<C> *name##Handler(C *pObj, void (C::*pFunc)parmdecl)
{
return new name##Delegate::TFunctor<C>(pObj, pFunc);
}
#endif // DELEGATE_H__
#include <iostream>
#include "delegate.h"
using namespace std;
DECLARE_DELEGATE(Add, (int p1, float p2), (p1, p2))
class A
{
public:
A() { value = 5; }
virtual void Fun1(int val, float val2)
{
value = val*2*(int)val2;
cout << "[A::Fun1] " << val << ", " << val2 << endl;
}
static void StaticFunc(int val, float val2)
{
cout << "[A::StaticFunc] " << val << ", " << val2 << endl;
}
public:
int value;
};
class B : public A
{
public:
void Fun1(int val, float val2)
{
value += val*3*(int)val2;
cout << "[B::Fun1] " << val << ", " << val2 << endl;
}
};
void GlobalFunc(int val, float val2)
{
cout << "[GlobalFunc] " << val << ", " << val2 << endl;
}
unsigned int WinSize(unsigned char *ColCnt,
unsigned char *RowCnt)
{
unsigned short result;
__asm {
mov ax, 1416h
int 10h
mov result, cx
les edi, ColCnt
mov es:[edi], bl //error illegal reference to 16-bit data in 'first operand’
les di, RowCnt
mov es:[edi], bh // the same problem
}
return(result);
}
int main()
{
// Create class instances
A a;
B b;
// Create an instance of the delegate
AddDelegate::Delegate del;
// Add our handlers
del += AddHandler(&a, &A::Fun1); // or del.Add(&a, A::Fun1);
del += AddHandler(&b, &B::Fun1); // or del.Add(&b, B::Fun2);
del += GlobalFunc; // or del.Add(GlobalFunc);
del += A::StaticFunc; // or del.Add(A::StaticFunc);
// Invoke the delegate
del(4, 5); // or del.Invoke(4, 5);
// Print the class values
cout << "[main] a.value = " << a.value << endl;
cout << "[main] b.value = " << b.value << endl;
// Remove some of the handlers
del -= AddHandler(&a, &A::Fun1); // or del.Remove(&a, A::Fun1);
del -= A::StaticFunc; // or del.Remove(A::StaticFunc);
// Invoke the delegate again
del(4, 5); // or del.Invoke(4, 5);
// Print the class values
cout << "[main] a.value = " << a.value << endl;
cout << "[main] b.value = " << b.value << endl;
return 0;
}