C++中实现.NET风格的委托

 
这几天在看C#的时候, 发现其委托这种机制非常的先进,因为自己工作中用的较多的是C++,于是便有了在C++中实现它的想法。先在网上搜了一下,便发现了这篇好文,个人觉得其实现是很“美”的,于是便翻译了过来。(欢迎批评指正)
 
目录
  • 引言
  • 什么是委托?
  • 正文
    • 函数对象(functor)概述
    • 利用宏(macro)实现函数对象参数化
    • 实现委托
  • 如何使用
  • 帮助
  • 后续功能
  • 版本信息
引言
 
.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
    int operator ()( 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)
    virtual int operator ()( 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 ())
    int operator ()( 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
        return 0 ;
}
 
这是一个简单的类, 它包含了一个符合函数对象要求的函数-以一个 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;
 
    return 0 ;
}
 
产生结果如下:
 
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;
 
    return 0 ;
}
 
结果如下:
 
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 :                                                             /
        virtual void operator () 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 */      /
        void operator ()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 :
        virtual void operator () ( 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 */
        void operator ()( 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() 操作符,第一行是宏, 第二行是展开后的代码 :
 
void operator ()parmdecl            { (m_pObj->*m_pFunc)parmcall; }
void operator ()( 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 */                                         /
        void operator +=(Functor *pFunc);                               /
        void operator +=( void (*pFunc)parmdecl);                        /
        /* Subtraction operators */                                      /
        template < class C>                                               /
        void operator -=(TFunctor<C> *pFunc);                           /
        void operator -=( void (*pFunc)parmdecl);                        /
                                                                        /
        /* Calls all the callbacks in the callback list */               /
        void Invoke parmdecl;                                           /
        /* Calls all the callbacks in the callback list */               /
        void operator ()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 ; }
    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;
}
 
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 ;
}
 
这个例子展示了委托几乎所有的操作,其结果如下:
 
[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() .
  • 增加一个宏-参数化的类来支持返回类型,为委托中每个函数对象存储返回值用以之后访问
  • 加一些支持固定参数个数的模板类,如只带一个参数的类,或只带两个参数的类等),这可能需要或不需要在量的类来实现-为委托的返回值或其它功能提供不同类型的类
  • 建议?
 
 版本信息
  • 20038-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 ;
}

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值