A system method for establishing an inter-object message connection in C ++

zhaozj2021-02-11  200

A system method for establishing an inter-object message connection in C

Item

Users who have used C over-object-oriented programming are known, and the objects in the program rarely exist. Almost impossible to consider the interaction between the objects. Therefore, identifying the relationship between the object or the message connection between the establishment of the object is an important task for object-oriented programming. This paper focuses on the perspective of C programming, proposes a practical method for establishing a message connection between an object. If you want to learn more about the object programming technology in detail, please refer to the monograph. Everyone knows that the object is a package of data and methods. In C , they behave separately as data members and member functions. Program designers change the status of the object by performing the various methods of the object (ie, change the properties data of the object). This makes some "events" in this object. When an object occurs an event, it usually needs to send "messages" to other related objects, requesting them to make some processing. At this time, an event occurs and processed to other objects is called an "event object", and the object of the handling event is called "callback object". The processing of the callback object is called "callback function". In C , this process is equivalent to: When an event object occurs, call some member functions of the callback object. The usual method is to transfer the object pointer to the event object to the event object. But this method is not universal. In order to reduce the workload of programming, this paper proposes a system method for establishing a message connection between an object. Its idea is: Abstract "Events → Request Handling → Perform Processing" into a "callback" class. By inheritance, users can easily obtain the mechanism of establishing a message connection between the object.

First, the data structure of the callback class and its member functions

The Callback class proposed in this article supports three callback functions. They are: the member function in the callback object, belongs to the static member function of the callback class and the normal C function. The Callbackle class contains a modular function table CallbackList. It is used to record the event name, pointing to the pointer to the callback function and the callback object. Each node of the table is an event record EventRecord. Each event record contains three domains: Event Name Pointer EventName, pointer Pointertocbo, pointing to the callback object Pointertocbf or Pointertocbsf (where Pointertocbf points to the member function of the callback object, Pointertocbsf points to the static member function of the callback class or ordinary Function. They are in a usual use body). The callback mechanism provided by the Callback class is this: the callback function in the registration of the callback object is registered on the event object; when the event occurs, the event object retrieves and executes the callback function in its callback table. This makes the message connection of the two. (For specific implementations of this class, please refer to the list of procedures attached to the article)

Callback

Class member function

AddCallback

Used to register the callback function to the callback table of the event object. It has two overload versions:

Void Callback :: AddCallback (Char * Event, CallbackFunction CBF, Callback * P);

Void Callback :: AddCallback (Char * Event, CallbackStaticFunction CBSF);

Among them, the first addCallback is used to register a member function of a callback object to the callback table of the event object. The second addCallback is used to register or call the static member function of a call to register in the callback table of the event object. In the top parameter table, Event is a pointer to the event name string, and P is a pointer to the callback object, and the CBF and CBSF are pointers that point to member functions and static member functions (or ordinary functions). When the callback function from a callback object SomeObject, transfer member function pointer should be formatted as follows: (CallBackFunction) & SomeObject :: MemberFunctionName; transmitting a static class member function pointer SomeObject format should be used: (CallBackStaticFunction) & SomeObject :: FunctionName; transfer When a normal function pointer is a general function pointer, you only need to pass a function name. The member function void callback :: CallCallback (char * ename, calldata calldata = null) is used to call all callback functions registered on the event ename. Among them, CallData is a data pointer (CallData is actually void *, see a list of procedures). Event objects can pass useful data to the callback object. The member function is typically called in the member function of the event object, as usual only if the member function of the event object can change the internal data of the object, thereby causing some events.

Member function RemoveCallback is used to delete the callback function registered on the event object. Its three overload versions are:

Void Callback :: RemoveCallback (Char * Event, CallbackFunction CBF, Callback * P);

Void Callback :: RemoveCallback (Char * Event, CallbackStaticFunction CBSF);

Void Callback :: RemoveCallback (Char * Event);

Among them, Event, CBF, CBSF, P or other parameters are the same as the member function addCallback. The first RemoveCallback is used to delete a member function that registers a callback object on the event Event. The second RemoveCallback is used to delete a static member function that registers a normal function or a tempering class on an event Event. The third REMOVALLBACK is used to delete all the callback functions registered on the event EVENT.

Second, the use of the Callback class

With the Callback class, you can do it as follows:

1. Determine which objects in the program have a relationship, requiring a message connection. And determine which object is an event object in each particular message connection relationship, which object is a callback object.

2. Event object classes and callback object classes must be inherited from the Callback class to get a callback support.

3. Register the callback data for the event object. Including: event name, callback function name, pointing to the pointer to the callback object.

4. When you are interested in incident, call the CallCallback function in the member function of the event object class.

Here is a specific example. By it will learn more about the use 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 volume function {

Volume = V;

IF (Volume> 20) {// "Volume greater than 20" incident happened

// Call the callback function registered on the two events

CallCallback ("Volume change");

CallCallback ("Volume is greater than 20", & volume);

}

}

Void DecreaseVolume (int V) // Dissumer Members

{

Volume - = v;

IF (Volume <5) {// "The volume is less than 5" incident happened

// Call the callback function registered on the two events

CallCallback ("Volume change");

CallCallback ("The volume is less than 5", & volume);

}

}

}

// "Ear" class

Class Ear: Public Callback

{

PUBLIC:

Static Void Response (CallData CallData) / / Reaction of "Volume Change"

{

Cout << "The volume changed." << Endl;

}

Void highvoiceresponse (calldata calldata) // Reaction to the treble

{

Cout << "Hey! Too noisy! The volume is:" << *) CallData) << ENDL;

}

Void LowVoicesResponse (CallData CallData) / / Reaction of Bass

{

Cout << "! I can't hear it. Now the volume is:" << *) CallData) << end1

}

}

Void main (void)

{

Speaker S (10); // Today's volume is 10

Ear e;

/ / Register the callback function for the event object S

S.addCallback ("Volume greater than 20", (CallbackFunction) & Ear :: HighvoicesResponse, & E);

S.addCallback ("CallbackFunction) & Ear :: LowvoicesResponse, & E);

S.addCallback ("Volume Change", (CallbackStaticFunction) & Ear :: response);

S.incReasevolume (12); // increase the volume 12, now the volume bit 22

S.Decreasevolume (20); // Reduce volume 20, now volume bit 2

}

operation result:

The volume changed.

Hey! It's noisy! The volume is: 22

The volume changed.

what! I can't hear it. The volume is: 2

In the above example, the speaker object S is an event object, the ear object e is a callback object. . Some of the three events were registered: "The volume changed", "volume is greater than 20", "volume is less than 5". The callback function is: Ear :: Response, Ear :: Highvoiceerestsponse, Ear :: lowvoiceerestsponse. When the speaker S changes the volume through its member functions Increasevolume and DecReaseVolume, the callback object E will automatically react. It can be seen that the establishment of a message connection between the objects has become a simple and beautiful work by using the Callback class.

Because the author's level is limited, the design of this class must be imperfect. If you are interested in it, the author can discuss such issues with you C players. Contact: fei_xiang@263.net attached: Program list (this program is compiled in MS VC 5.0 and TC 3.0)

// Classic structure of the Tune class: Callback.h

#ifndef _callback_h

#define _callback_h

#include

#include

#include

#define callbacklist_init_size 10

#define callbacklist_increment 5

Class Callback;

TypeDef void * calldata; // Tune Data Pointer Type Definition

TypeDef void (callback :: * callbackfunction); // Pointer to the callback member function

TypeDef void (* callbackstaticfunction) (CallData); // Pointer to static member functions or generic type definitions

Class EventRecord {

Private:

Char * Eventname; // Tune Event Name

Callback * pointertocbo; // Pointer to the callback object

// Pointer to the member function and the common body pointing to a static member function (or a normal function) pointer

Union {

Callbackfunction Pointertocbf;

Callbackstaticfunction Pointertocbsf;

}

PUBLIC:

EventRecord (void); // Event record class default constructor

// Construct an event record containing member functions

EventRecord (Char * ENAME, CALLBACK * PCBO, CallbackFunction PCBF);

// Construct an event record containing static member functions or normal functions

EventRecord (Char * ENAME, CALLBACKSTACFUNCTION PCBSF);

~ EventRecord (void); // Destructure event record

Void Operator = (const eventRecord & ER); // Overloaded assignment operator

/ / Judgment whether the event name of the current event record is ENAME

INT Operator == (char * ename) Const;

/ / Judgment whether the current event log is equal to the specified event record

INT Operator == (Const EventRecord & Er) Const;

Void flush (void); // empty the current event record

INT ISEMPTY (VOID) const; // Judgment Event Record is empty (ie, whether the event name is empty)

Friend class calback;

/ / Let the Callback class access to the private member of EventRecord;

}

Class callback {

Private:

EventRecord * CallbackList; // Tune incident table

INT Curpos; // Current event record location

INT LastPOS; // The last idle location in the reconciliation table

INT size; // The size of the retraction table

Void movefirst (void) {curpos = 0;} // set the current record as the first record

Void MoveNext (Void) // Put the next record as the current record

{

IF (curpos == lastpos) return;

Curpos ;}

/ / Judgment whether the callback watch is traversed

INT endoflist (void) const {return curpos == lastpos;

PUBLIC:

Callback (void); // Constructor

Callback (const callback & cb); // copy constructor

~ Callback (void); // Destructor

Void Operator = (const callback & cb); // Overload assignment operator

/ / Put the member function of the callback object, static member function (or ordinary function)

// Register the callback function of the 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 the records of an event

/ / Perform all callback functions registered on a certain event

Void CallCallback (Char * Event, CallData CallData = NULL);

}

#ENDIF

// Realization of Call Tune: Callback.cpp

#include "callback.h"

// EventRecord class implementation

EventRecord :: EventRecord (Void)

{

Eventname = null;

Pointertocbo = NULL;

// Because Sizeof (CallbackFunction)> sizeof (CallbackStaticFunction)

Pointertocbf = NULL;

}

EventRecord :: EventRecord (Char * ENAME, CALLBACK * PCBO, CALLBACKFUNCTION PCBF)

: Pointertocbo (PCBO), Pointertocbf (PCBF)

{

Eventname = strDUp (ename);

}

EventRecord :: EventRecord (Char * ENAME, CALLBACKSTATICFUNCTION PCBSF)

: Pointertocbo (NULL), Pointertocbsf (PCBSF)

{

Eventname = strDUp (ename);

}

EventRecord :: ~ EventRecord (Void)

{

Eventname Delete EventName;

}

Void EventRecord :: Operator = (Const EventRecord & Er)

{

IF (er.eventname)

Eventname = strdup (er.eventname);

Else

Eventname = null;

Pointertocbo = Er.Pointertocbo;

Pointertocbf = Er.Pointertocbf;

}

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) / * Er and EventName cannot be swapped * /

&& (Pointertocbo == Er.Pointertocbo)

&& (Pointertocbo?

(Pointertocbf == Er.Pointertocbf):

(Pointertocbsf == Er.Pointertocbsf);

}

Void EventRecord :: Flush (void)

{

IF (eventname) {

Delete Eventname;

Eventname = null;

}

Pointertocbo = NULL;

Pointertocbf = NULL;

}

Int EventRecord :: ISempty (Void) Const

{

IF (eventname == null)

Return 1;

Else

Return 0;

}

// Callback class implementation

Callback :: Callback (void)

{

/ / Allocate memory space by the initial size

Callbacklist = new evenetrecord [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);

}

// One copy of each event record

For (int i = 0; i

}

Void Callback :: Operator = (Const Callback & Cb)

{

Curpos = cb.curpos;

Lastpos = cb.lastpos;

SIZE = Cb.size;

Delete [] CallbackList; // Delete the old callback watch

Callbacklist = new eventRecord [size]; // Reassign the memory space

IF (! CallbackList) {

CERR << "Callback: Memory Allocation Error." << endl;

Exit (1);

}

// One copy of each event record

For (int i = 0; i

}

Callback :: ~ Callback (void)

{

DELETE [] CallbackList;

}

Void Callback :: AddCallback (Char * Event, CallbackFunction PCBF, CALLBACK * PCBO) {

/ / If the event is empty, exit

IF ((Event == NULL)? 1: (Strlen (Event) == 0)) Return;

// Look for the first idle position generated by deleting event records, and fill in new event records

For (int start = 0; start

IF (CallbackList [Start] .Isempty ()) {

CallbackList [start] = EventRecord (Event, PCBO, PCBF);

Break;

}

IF (start

/ / No idle position, add new records after the callback form

IF (LastPOS == size) // The callback watch is full, you need to "elongate"

{

EventRecord * Templist = CallbackList; // State the old callback pointer

// Take a certain step "elongation"

CallbackList = New EventRecord [Size CallbackList_Increment];

IF (! CallbackList) {

CERR << "Callback: Memory Allocation Error." << endl;

Exit (1);

}

/ / Copy the record in the old reconversion table

For (int i = 0; i

Delete [] templist; // Delete old reconvers

Size = CallbackList_increment; // Remember the size of the new reconversion 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 PCBSF)

{

IF ((Event == NULL)? 1: (Strlen (Event) == 0)) Return;

For (int start = 0; start

IF (CallbackList [Start] .Isempty ()) {

Callbacklist [start] = EventRecord (Event, PCBSF);

Break;

}

IF (Start

IF (LastPos == Size) // Event List is InsufFCIENT

{

EventRecord * Templist = CallbackList;

CallbackList = New EventRecord [Size CallbackList_Increment];

IF (! CallbackList) {

CERR << "Callback: Memory Allocation Error." << endl;

Exit (1);

}

For (int i = 0; i

DELETE [] Templist;

SIZE = CallbackList_increment;

}

CallbackList [lastpos] = EventRecord (Event, PCBSF);

LastPOS ;

}

// Delete member functions registered on specified events

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

IF (CallbackList [i] == ER) CallbackList [i] .flush ();

}

/ / Delete Static member functions or ordinary functions registered on specified events

Void Callback :: RemoveCallback (Char * Event, CallbackStaticFunction PCBSF)

{

IF ((Event == NULL)? 1: (Strlen (Event) == 0)) Return;

EventRecord Er (Event, PCBSF);

For (int i = 0; i

IF (CallbackList [i] == ER) CallbackList [i] .flush ();

}

/ / Delete all callback functions registered on specified events

Void Callback :: RemoveCallback (Char * Event)

{

IF ((Event == NULL)? 1: (Strlen (Event) == 0)) Return;

For (int i = 0; i

IF (CallbackList [i] == Event) CallbackList [i] .flush ();

}

Void Callback :: CallCallback (Char * Event, CallData CallData)

{

IF ((Event == NULL)? 1: (Strlen (Event) == 0)) Return;

Callback * PCBO;

Callbackfunction PCBF;

Callbackstaticfunction PCBSF;

Movefirst ();

While (! endoflist ())

{

// Transfer to the next record to continue loop, such as the current event record and the specified event does not match

IF (! (CallbackList [CURPOS] == Event))

{

MoveNext ();

CONTINUE;

}

/ / If you find a matching record

PCBO = CallbackList [CURPOS] .pointertocbo;

// If the callback target pointer is empty in the event record, it will indicate that the static function pointer is saved.

IF (PCBO == NULL) {

PCBSF = CallbackList [CURPOS] .pointertocbsf;

PCBSF (CallData); // Call the static callback function

}

ELSE // If the callback object pointer is non-empty, it will indicate that the member function pointer is saved.

{

PCBF = CallbackList [Curpos] .pointertocbf;

(PCBO -> * PCBF) (CallData); // Call the member function of the callback object

}

MoveNext ();

}

}

转载请注明原文地址:https://www.9cbs.com/read-4540.html

New Post(0)