Use of callback functions (4)

Source: Internet
Author: User
Tags call back

We all know that objects are the encapsulation bodies of data and methods. In C ++, they are data members and member functions. The program designer changes the object state by executing various methods of the object (that is, changing the attribute data of the object ). In this way, some "events" occur to this object ". When an object has an event, it usually needs to send a "message" to other related objects and request them for some processing. At this time, the object that occurs and requests to other objects is called the "event object", and the object that handles the event is called the "Callback object ". A callback object is called a callback function to process events ". In C ++, this process is equivalent to calling some member functions of the callback object when an event occurs. Generally, the callback object transmits the object pointer to the event object. However, this method is not universal. In order to reduce the workload of program design, this paper proposes a system method for establishing message connections between objects. The idea is to abstract the process "event occurrence> request processing> Execution Processing" into a "Callback" class. With inheritance, you can easily obtain the mechanism for establishing message connections between objects.

I. Data Structure and member functions of the callback class

The callback class proposed in this article supports three types of callback functions. They are member functions in the callback object, static member functions and common C functions in the callback class. The callback class contains a callback function table callbacklist. It is used to record the event name and point to the callback function and the pointer to the callback object. Each node in the table is an event record eventrecord. Each event record contains three domains: The event name pointer eventname, the pointer to the callback object pointertocbo, And the pointer to the callback function pointertocbsf or pointertocbsf (wherein, pointertocvr points to the member function of the callback object, pointertocbsf points to the static member function or common function of the callback class. ). The callback mechanism provided by the callback class is as follows: register the callback function in the callback object on the event object; when an event occurs, the event object retrieves and executes the callback function in its callback table. So that the message connection between the two can be established. (For the specific implementation of this class, see the program list attached to the article) callback object

Event object

Event name Callback object pointer Callback function pointer
"Event" Pointercbo Pointertocbsf or pointertocbsf


Addcallback: registers the event name and the pointer to the callback function and the callback object.

Callcallback: In the callback table, retrieve the callback functions registered on the specified event and call them.

Call the callcallback function when an event occurs.

Member functions that process event

Callbacklist inherited from the callback class, which includes the member functions addcallback and callback.

When the callback function is a static member function or a common C function, pointertocbo is null.

The event name is the retrieval keyword in the callback table callbacklis.

Other member functions in the callback object

The member function addcallback of the callback class is used to register the callback function to the callback table of the event object. It has two overloaded versions.

Void callback: addcallback (char * event, callbackfunction CBF, callback * P );
Void callback: addcallback (char * event, callbackstaticfunction cbsf );

The first addcallback is used to register the member functions of a callback object to the callback table of the event object. The second addcallback is used to register static member functions of a callback class to the callback table of the event object. In the preceding parameter table, event is the pointer to the event name string, p is the pointer to the callback object, and cbsf is the pointer to the member function and static member function (or common function) respectively) pointer. When a callback function comes from a callback object someobject, the passed member function pointer should adopt the following format: (callbackfunction) & someobject: memberfunctionname; when passing a static member function pointer of the someobject class, the format should be: (callbackstaticfunction) & someobject: functionname; when passing a common function pointer in a program, you only need to pass the function name.

The callback class member function void callback: callcallback (char * ename, calldata = NULL) is used to call all the callback functions registered on the event ename. Among them, calldata is the Data Pointer (calldata is actually void *, see the program list ). The event object can pass useful data to the callback object. This member function is usually called in the member function of the event object, because only the member function of the event object can change the internal data of the object, so that some events occur.
The member function removecallback is used to delete the callback function registered on the event object. The three overloaded versions are as follows:

Void callback: removecallback (char * event, callbackfunction CBF, callback * P );
Void callback: removecallback (char * event, callbackstaticfunction cbsf );
Void callback: removecallback (char * event );


Among them, parameters such as event, cbsf, and P are the same as those in the member function addcallback. The first removecallback is used to delete a member function registered with a callback object on the event. The second removecallback is used to delete a common function registered on the event or a static member function of a callback class. The third removecallback is used to delete all callback functions registered on the event.


Ii. usage of the callback class
To use the callback class, follow these steps:
1. Determine which objects in the program have a relationship and establish a message connection. Determine which object is the event object and which is the callback object in the connection relationship of each specific message.
2. Both the event object class and the callback object class must inherit from the callback class to obtain callback support.
3. Register callback data for the event object. Including the event name, callback function name, and pointer to the callback object.
4. When an event you are interested in occurs, call the callcallback function in the member function that triggers the event in the event object class.
The following is a specific example. You will have a better understanding of the usage of the callback class.

// Test program file: Test. cpp
# Include "Callback. H"
// Speaker class
Class Speaker: Public callback
{
PRIVATE:
Int volume;
Public:
Speaker (int v): volume (v ){}
Void increasevolume (INT v) // adds the volume member function.
{
Volume + = V;
If (volume> 20) {// "volume greater than 20" event occurred
// Call the callback function registered on two events
Callcallback ("volume changed ");
Callcallback ("volume greater than 20", & volume );
}
}
Void decreasevolume (INT v) // function for reducing the volume of a member
{
Volume-= V;
If (volume <5) {// "volume less than 5" event occurred
// Call the callback function registered on two events
Callcallback ("volume changed ");
Callcallback ("volume less than 5", & volume );
}
}

// "Ears" Type
Class ear: Public callback
{
Public:
Static void response (calldata) // response to "volume change"
{
Cout <"the volume has changed." <Endl;
}

Void highvoiceresponse (calldata) // high-pitched response
{
Cout <"hello! Too noisy! The current volume is: "<* (int *) calldata) <Endl;
}
Void lowvoiceresponse (calldata) // response to the bass
{
Cout <"Ah! I cannot hear it. The current volume is: "<* (int *) calldata) <Endl;
}
};
Void main (void)
{
Speaker S (10); // The current volume is 10
Ear E;

// Register the callback function for event object s
S. addcallback ("volume greater than 20", (callbackfunction) & ear: highvoiceresponse, & E );
S. addcallback ("volume less than 5", (callbackfunction) & ear: lowvoiceresponse, & E );
S. addcallback ("volume changed", (callbackstaticfunction) & ear: Response );
S. increasevolume (12); // increase the volume by 12. The current volume is 22
S. decreasevolume (20); // reduce the volume by 20. Now the volume is 2
}

Running result:
The volume has changed.
Hello! Too noisy! The current volume is 22.
The volume has changed.
Ah! I cannot hear it. The current volume is: 2
In the preceding example, the speaker object S is the event object, and the ear Object E is the callback object .. Three events are registered on S: "volume changed", "volume greater than 20", and "volume less than 5 ". The callback functions are: ear: Response, ear: highvoiceresponse, and ear: lowvoiceresponse. When the speaker s changes the volume through its member functions increasevolume and decreasevolume, the callback Object E automatically responds. It can be seen that using the callback class makes it easy and elegant to establish a message connection between objects.

Appendix: program list (this program is compiled on ms vc ++ 5.0 and TC ++ 3.0)

// Class structure of the callback class: callback. h
# Ifndef _ callback_h
# DEFINE _ callback_h
# Include <stdlib. h>
# Include <string. h>
# Include <iostream. h>
# Define callbacklist_init_size 10
# Define callbacklist_increment 5
Class callback;
Typedef void * calldata; // callback Data Pointer Type Definition
Typedef void (callback: * callbackfunction) (calldata); // pointer to the callback member function
Typedef void (* callbackstaticfunction) (calldata); // pointer type definition pointing to a static member function or a common function
Class eventrecord {
PRIVATE:
Char * eventname; // callback event name
Callback * pointertocbo; // pointer to the callback object
// Pointer to the member function and the shared body pointing to the static member function (or common function) pointer
Union {
Callbackfunction pointertocvr;
Callbackstaticfunction pointertocbsf;
};
Public:
Eventrecord (void); // default constructor of the event record class
// Construct event records containing member functions
Eventrecord (char * ename, callback * pcbo, callbackfunction pcbf );
// Construct event records that contain static member functions or common functions
Eventrecord (char * ename, callbackstaticfunction extends SF );
~ Eventrecord (void); // destructor event record
Void operator = (const eventrecord & Er); // overload value assignment operator
// Determine whether the event name recorded by the current event is ename
Int operator = (char * ename) const;
// Determine whether the current event record is equal to the specified event record
Int operator = (const eventrecord & Er) const;
Void flush (void); // clears the current event record
Int isempty (void) const; // determines whether the event record is empty (that is, whether the event name is empty)
Friend class callback; // enables the callback class to access private members of eventrecord;
};
Class callback {
PRIVATE:
Eventrecord * callbacklist; // callback event table
Int curpos; // the location of the current event record
Int lastpos; // The Last idle position in the callback table
Int size; // the size of the callback table.
Void movefirst (void) {curpos = 0;} // set the current record to the first record
Void movenext (void) // set the next record to the current record
{
If (curpos = lastpos) return;
Curpos ++;
}
// Determine whether the callback table has been traversed
Int endoflist (void) const {return curpos = lastpos ;}
Public:
Callback (void); // Constructor
Callback (const callback & CB); // copy the constructor
~ Callback (void); // destructor
Void operator = (const callback & CB); // overload value assignment operator
// Call back the member functions and static member functions (or common functions) of the object)
// Callback function registered as an event object
Void addcallback (char * event, callbackfunction CBF, callback * P );
Void addcallback (char * event, callbackstaticfunction cbsf );
// Delete the callback function registered on the specified event
Void removecallback (char * event, callbackfunction CBF, callback * P );
Void removecallback (char * event, callbackstaticfunction cbsf );
Void removecallback (char * event); // delete all records of an event
// Execute all the callback functions registered on an event
Void callcallback (char * event, calldata = NULL );
};
# Endif
// Implementation of the callback class: callback. cpp
# Include "Callback. H"
// Implement the eventrecord class
Eventrecord: eventrecord (void)
{
Eventname = NULL;
Pointertocbo = NULL;
// Because sizeof (callbackfunction)> sizeof (callbackstaticfunction)
Pointertocbn = NULL;
}
Eventrecord: eventrecord (char * ename, callback * pcbo, callbackfunction pcbf)
: Pointertocbo (pcbo), pointertocvr (pcbf)
{
Eventname = strdup (ename );
}
Eventrecord: eventrecord (char * ename, callbackstaticfunction extends SF)
: Pointertocbo (null), pointertocbsf (sort SF)
{
Eventname = strdup (ename );
}
Eventrecord ::~ Eventrecord (void)
{
If (eventname) delete eventname;
}
Void eventrecord: Operator = (const eventrecord & Er)
{
If (ER. eventname)
Eventname = strdup (ER. eventname );
Else
Eventname = NULL;
Pointertocbo = ER. pointertocbo;
Pointertocbr = ER. pointertocbr;
}
Int eventrecord: Operator = (char * ename) const
{
If (eventname = NULL) | ename = NULL)
Return eventname = ename;
Else
Return strcmp (eventname, ename) = 0;
}
Int eventrecord: Operator = (const eventrecord & Er) const
{
Return (ER = eventname)/* the location of ER and eventname cannot be changed */
& (Pointertocbo = ER. pointertocbo)
& (Pointertocbo?
(Pointertocbr = ER. pointertocbr ):
(Pointertocbsf = ER. pointertocbsf ));
}
Void eventrecord: flush (void)
{
If (eventname ){
Delete eventname;
Eventname = NULL;
}
Pointertocbo = NULL;

Pointertocbn = NULL;
}
Int eventrecord: isempty (void) const
{
If (eventname = NULL)
Return 1;
Else
Return 0;
}
// Callback class implementation
Callback: callback (void)
{
// Allocate memory space for the callback table based on the initial size
Callbacklist = new eventrecord [callbacklist_init_size];
If (! Callbacklist ){
Cerr <"Callback: Memory Allocation Error." <Endl;
Exit (1 );
}
Size = callbacklist_init_size;
Lastpos = 0;
Curpos = 0;
}
Callback: callback (const callback & CB): curpos (CB. curpos), lastpos (CB. lastpos), size (CB. Size)
{
Callbacklist = new eventrecord [size];
If (! Callbacklist ){
Cerr <"Callback: Memory Allocation Error." <Endl;
Exit (1 );
}
// Copy all event records one by one
For (INT I = 0; I <size; I ++) callbacklist [I] = CB. callbacklist [I];
}
Void callback: Operator = (const callback & CB)
{
Curpos = CB. curpos;
Lastpos = CB. lastpos;
Size = CB. size;
Delete [] callbacklist; // Delete the old callback table
Callbacklist = new eventrecord [size]; // re-allocate memory space
If (! Callbacklist ){
Cerr <"Callback: Memory Allocation Error." <Endl;
Exit (1 );
}
// Copy all event records one by one
For (INT I = 0; I <size; I ++) callbacklist [I] = CB. callbacklist [I];
}
Callback ::~ Callback (void)
{
Delete [] callbacklist;
}
Void callback: addcallback (char * event, callbackfunction pcbf, callback * pcbo)
{
// Exit if the event name is empty
If (event = NULL )? 1 :( strlen (event) = 0) return;
// Find the first idle location generated by deleting the event record, and fill in the new event record
For (INT start = 0; Start <lastpos; Start ++)
If (callbacklist [start]. isempty ()){
Callbacklist [start] = eventrecord (event, pcbo, pcbf );
Break;
}
If (start <lastpos) return; // there is indeed a free location
// There is no idle position, and a new record is appended to the callback table
If (lastpos = size) // The callback table is full and needs to be stretched"
{
Eventrecord * templist = callbacklist; // save the old callback table pointer
// Call back the table with a certain step size.
Callbacklist = new eventrecord [size + callbacklist_increment];
If (! Callbacklist ){
Cerr <"Callback: Memory Allocation Error." <Endl;
Exit (1 );
}
// Copy the records in the old callback table
For (INT I = 0; I <size; I ++) callbacklist [I] = templist [I];
Delete [] templist; // Delete the old callback table
Size + = callbacklist_increment; // write down the size of the new callback table
}
// Construct a new event record and fill it in the callback table
Callbacklist [lastpos] = eventrecord (event, pcbo, pcbf );
Lastpos ++;
}
Void callback: addcallback (char * event, callbackstaticfunction extends SF)
{
If (event = NULL )? 1 :( strlen (event) = 0) return;
For (INT start = 0; Start <lastpos; Start ++)
If (callbacklist [start]. isempty ()){
Callbacklist [start] = eventrecord (event, callback SF );
Break;
}
If (start <lastpos) return; // a hole is found
If (lastpos = size) // event list is insufficient
{
Eventrecord * templist = callbacklist;

Callbacklist = new eventrecord [size + callbacklist_increment];

If (! Callbacklist ){
Cerr <"Callback: Memory Allocation Error." <Endl;
Exit (1 );
}
For (INT I = 0; I <size; I ++) callbacklist [I] = templist [I];
Delete [] templist;
Size + = callbacklist_increment;
}

Callbacklist [lastpos] = eventrecord (event, callback SF );
Lastpos ++;
}

// Delete the member functions registered on the specified event
Void callback: removecallback (char * event, callbackfunction pcbf, callback * pcbo)
{
If (event = NULL )? 1 :( strlen (event) = 0) return;
Eventrecord Er (event, pcbo, pcbf );

For (INT I = 0; I <lastpos; I ++)
If (callbacklist [I] = ER) callbacklist [I]. Flush ();
}

// Delete static member functions or common functions registered on the specified event
Void callback: removecallback (char * event, callbackstaticfunction extends SF)
{
If (event = NULL )? 1 :( strlen (event) = 0) return;
Eventrecord Er (event, notify SF );

For (INT I = 0; I <lastpos; I ++)
If (callbacklist [I] = ER) callbacklist [I]. Flush ();
}
// Delete All callback functions registered on the specified event
Void callback: removecallback (char * event)
{
If (event = NULL )? 1 :( strlen (event) = 0) return;
For (INT I = 0; I <lastpos; I ++)
If (callbacklist [I] = event) callbacklist [I]. Flush ();
}

Void callback: callcallback (char * event, calldata)
{
If (event = NULL )? 1 :( strlen (event) = 0) return;
Callback * pcbo;
Callbackfunction pcbf;
Callbackstaticfunction extends SF;
Movefirst ();
While (! Endoflist ())
{
// If the current event record does not match the specified event, transfer it to the next record to continue the loop.
If (! (Callbacklist [curpos] = event ))
{
Movenext ();
Continue;
}
// If a matching record is found
Pcbo = callbacklist [curpos]. pointertocbo;
// If the callback object pointer in the event record is null, the record stores the static function pointer.
If (pcbo = NULL ){
Required Sf = callbacklist [curpos]. pointertocbsf;
Pcbsf (calldata); // call this static callback function
}
Else // If the callback object pointer in the event record is not null, it indicates that the record stores the member function pointer.
{
Pcbf = callbacklist [curpos]. pointertocbr;
(Pcbo-> * pcbf) (calldata); // call the member function of the callback object
}
Movenext ();
}
}

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.