C++实现.NET气势气魄的委托
副标题#e#
引言
在.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指针而不是派生模板类指针为参数。这是必须的, 因为每一个差异的模板参数发生的模板类都是差异的范例,直接用此模板类为参数就不能支持多种范例了。
#p#分页标题#e#
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;
};
#p#副标题#e#
这是一个简朴的措施,它建设两个引用同一类范例的函数工具的实例,针对两个同范例的差异的工具实例挪用函数工具,并显示功效.
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()操纵符,第一行是宏, 第二行是展开后的代码:
#p#分页标题#e#
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;
}
这个例子展示了委托险些所有的操纵,其功效如下:
#p#分页标题#e#
[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和以上给出的例子代码
类辅佐
因为代码是由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().
后续成果
增加一个宏-参数化的类来支持返回范例,为委托中每个函数工具存储返回值用以之后会见。
#p#分页标题#e#
加一些支持牢靠参数个数的模板类,如只带一个参数的类,或只带两个参数的类等),这大概需要或不需要在量的类来实现-为委托的返回值或其它成果提供差异范例的类。
发起?
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;
}