C + + implementation. NET-style delegates

Source: Internet
Author: User
Tags constructor

Introduction

In. NET, delegates are used to implement event handling. It allows a class (method) to register an event, and then this registered method is invoked when this event is raised. In the non. NET environment in C + +, this is not an easy task, especially the Non-static member function of the class, it is more difficult to do as a callback function. The goal of this article is to give a solution that allows static member functions of classes, non-static member functions, and class-not-member functions to be used like callback functions. This implementation attaches great importance to type safety, in order to maintain type safety we have omitted some features of the implementation.

What is a delegate?

. NET Framework defines a delegate as follows:

"A delegate is a class that can hold a reference to a method. Unlike other classes, the delegate class has its own signature (return value, parameter type, number), and can only reference methods that match its signature. A delegate can actually be viewed as a type-safe function pointer or callback function.

A class that provides delegates allows other functions or classes to register event handlers on this delegate. Then, when the delegate for this class is executed, it iterates through its list of processing functions, calls one after the other, and passes in the information passed to the delegate. The class that provides the delegate does not need to know how many processing functions the delegate registers, and the delegate will handle it.

Body

Function object (functor) overview

We use a function object (functor, function object) to implement a delegate in C + +. This allows a non-static member function to be invoked in the context of a particular object. We use template technology to ensure that any class type can be used on it. A basic function object (functor) is defined as follows:

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
};
This function object (functor) uses the function format: the return type is int, with an argument of type int. Operator operator () is the key to the function object. It makes a function object (functor) work like a function call. Its job is to call a function pointer stored inside a class every time it executes. The following code shows how to use this function object (functor):
class MyClass
{
Public:
int Square (int p) {return p * p;};
};
void Some_function ()
{
//Create a class to call into 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 would hold the value 25
}
Calling a function object (functor) is almost as convenient as calling the function itself, because the operator () operator is overloaded. It says "almost" because the pointer to the actual object is not being used-it is stored inside the function object (functor).

Yes, that's good, but why do we use function objects (functor) instead of functions themselves? Good question, when you know the signature (return value and argument) of the function you want to call without caring whether it is a member function of the class, is the member function of which class, the function object is very useful to localize this information inside the object, thereby calling all functions that have the same signature in a uniform way. Look at the following code , I divide them into several items to understand:

First, a function object that is represented by a pure virtual base class, with an int as the parameter, and a value of int. It has only one function, the virtual operator () operator, so that we can call the function object (functor) without knowing the actual object type of the instance of a function object.

//Abstract base class
class functor
{
Public:
//Invoke the functor (no implementation as it must is overridden)
Virtualintoperator () (int) = 0;
};
The following is a template class that can be instantiated as any class type, assuming that it also has a function that returns an int as a parameter. It derives from functor, so a pointer to a particular function object can be passed to any place where its base class object (functor) pointer is needed, so this function object can be invoked regardless of its true object type. In addition to the base class and class name, this class is exactly the same as the class given earlier:
//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
} ;
The following is a simple function that invokes the function object pointer and the parameter of the function as a parameter. Note that this is a parameter with a base class functor pointer instead of a derived template class pointer. This is required because each of the template classes produced by the different template parameters is a different type and cannot be supported by using this template class directly as a parameter.

int operateonfunctor (int i, functor *pfunc)
{
if (Pfunc)
Return (*pfunc) (i);
Else
Return0;
}
This is a simple class that contains a function that conforms to the requirements of the function object-takes an int as an argument and returns an int. Note that this function also uses a data member of the class, which means that the callback function should actually be executed in the context of the instance object, so a function object referencing a different object of the same class produces a different result:

Class ClassA
{
Public
ClassA (int i) {m_value = i;}
int Funca (int i)
{
return (m_value-i);
}
int m_value;
};

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.