溫馨提示×

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

C++程序設(shè)計(jì)如何建立對象間消息連接

發(fā)布時(shí)間:2021-11-30 15:52:20 來源:億速云 閱讀:168 作者:iii 欄目:編程語言

本篇內(nèi)容主要講解“C++程序設(shè)計(jì)如何建立對象間消息連接”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“C++程序設(shè)計(jì)如何建立對象間消息連接”吧!

一、回調(diào)類的數(shù)據(jù)結(jié)構(gòu)及其成員函數(shù)

本文提出的CallBack類支持三種回調(diào)函數(shù)。它們是:回調(diào)對象中的成員函數(shù),屬于回調(diào)類的靜態(tài)成員函數(shù)和普通的C函數(shù)。CallBackle類中包含一回調(diào)函數(shù)表callBackList。它用于記錄事件名稱,指向回調(diào)函數(shù)及回調(diào)對象的指針。該表的每一個(gè)節(jié)點(diǎn)為一個(gè)事件記錄EventRecord。每個(gè)事件記錄包含三個(gè)域:事件名指針eventName,指向回調(diào)對象的指針pointerToCBO,指向回調(diào)函數(shù)的指針pointerToCBF或pointerToCBSF(其中,pointerToCBF指向回調(diào)對象的成員函數(shù),pointerToCBSF指向回調(diào)類的靜態(tài)成員函數(shù)或普通函數(shù)。它們同處于一共用體內(nèi))。CallBack類所提供的回調(diào)機(jī)制是這樣的:在事件對象上注冊回調(diào)對象中的回調(diào)函數(shù);當(dāng)事件發(fā)生時(shí),事件對象在其回調(diào)表中檢索并執(zhí)行回調(diào)函數(shù)。從而使二者的消息連接得以建立。(關(guān)于該類的具體實(shí)現(xiàn),請參閱文后所附的程序清單)

事件名回調(diào)對象指針回調(diào)函數(shù)指針
“event”pointerCBOpointerToCBF或pointerTOCBSF

AddCallBack: 注冊事件名和指向回調(diào)函數(shù),回調(diào)對象的指針

CallCallBack: 在回調(diào)表中,檢索注冊在指定事件上回調(diào)函數(shù)并調(diào)用它們

事件發(fā)生時(shí),調(diào)用CallCallBack函數(shù)

對事件event進(jìn)行處理的成員函數(shù)

從CallBack類繼承的回調(diào)表callBackList, 成員函數(shù)AddCallBack和CallCallBack。

當(dāng)回調(diào)函數(shù)為靜態(tài)成員函數(shù)或普通C函數(shù)時(shí), pointerToCBO為NULL。

事件名是回調(diào)表callBackLis中的檢索關(guān)鍵字。

回調(diào)對象中其它成員函數(shù)

CallBack類的成員函數(shù)AddCallBack用來將回調(diào)函數(shù)注冊到事件對象的回調(diào)表中。它有兩個(gè)重載版本:

void CallBack::AddCallBack(char *event,CallBackFunction cbf,CallBack *p);   void CallBack::AddCallBack(char *event,CallBackStaticFunction cbsf);

其中,***個(gè)AddCallBack用來將某回調(diào)對象的成員函數(shù)注冊到事件對象的回調(diào)表中。第二個(gè)AddCallBack用來將或某回調(diào)類的靜態(tài)成員函數(shù)注冊到事件對象的回調(diào)表中。在上參數(shù)表中,event是指向事件名字符串的指針,p是指向回調(diào)對象的指針,cbf和cbsf分別是指向成員函數(shù)及靜態(tài)成員函數(shù)(或普通函數(shù))的指針。當(dāng)回調(diào)函數(shù)來自某回調(diào)對象SomeObject時(shí),傳遞成員函數(shù)指針應(yīng)采用如下格式:(CallBackFunction)&SomeObject::MemberFunctionName; 傳遞SomeObject類的某靜態(tài)成員函數(shù)指針應(yīng)采用格式:(CallBackStaticFunction)& SomeObject::FunctionName;傳遞程序中普通函數(shù)指針時(shí),只需傳遞函數(shù)名即可。

CallBack類的成員函數(shù)void CallBack::CallCallBack(char *ename, CallData calldata = NULL)用來調(diào)用注冊在事件ename上的所有回調(diào)函數(shù)。其中,calldata為數(shù)據(jù)指針(CallData實(shí)際上就是void*,詳見程序清單)。事件對象可通過它向回調(diào)對象傳遞有用的數(shù)據(jù)。該成員函數(shù)通常在事件對象的成員函數(shù)中調(diào)用,因?yàn)橥ǔV挥惺录ο蟮某蓡T函數(shù)才能改變對象的內(nèi)部數(shù)據(jù),從而使某些事件發(fā)生。

成員函數(shù)RemoveCallback用來刪除注冊在事件對象上的回調(diào)函數(shù)。它的三個(gè)重載版本依次為:

void CallBack::RemoveCallBack(char *event,CallBackFunction cbf,CallBack *p);   void CallBack::RemoveCallBack(char *event,CallBackStaticFunction cbsf);   void CallBack::RemoveCallBack(char *event);

其中,event,cbf,cbsf,p等參數(shù)和成員函數(shù)AddCallBack中各參數(shù)一樣。***個(gè)RemoveCallBack用于刪除注冊在事件event上某回調(diào)對象的一個(gè)成員函數(shù)。第二個(gè)RemoveCallBack用于刪除注冊在事件event上的某普通函數(shù)或某回調(diào)類的一個(gè)靜態(tài)成員函數(shù)。第三個(gè)RemoveCallBack用于刪除注冊在事件event上的全部回調(diào)函數(shù)。

二、CallBack類的使用方法

使用CallBack類,可按以下步驟進(jìn)行:

1.確定程序中哪些對象間存在關(guān)系,需要建立消息連接。并確定在各特定消息連接關(guān)系中,哪個(gè)對象是事件對象,哪個(gè)對象是回調(diào)對象。

2.事件對象類和回調(diào)對象類都必須從CallBack類繼承,以獲得回調(diào)支持。

3.為事件對象注冊回調(diào)數(shù)據(jù)。包括:事件名,回調(diào)函數(shù)名,指向回調(diào)對象的指針。

4.當(dāng)你感興趣的事件發(fā)生時(shí),在事件對象類引發(fā)事件的成員函數(shù)中調(diào)用CallCallBack函數(shù)。

下面是一個(gè)具體的例子。通過它你會(huì)對Callback類的使用方法有進(jìn)一步的了解。

//測試程序文件:test.cpp    #include"callback.h"   //“揚(yáng)聲器”類    class Speaker:public CallBack   {   private:   int volume;  public:   Speaker(int v): volume(v) {}  void IncreaseVolume(int v) //增加音量成員函數(shù)   {  volume += v;  if(volume > 20){ //“音量大于20”事件發(fā)生了   //調(diào)用注冊在兩事件上的回調(diào)函數(shù)   CallCallBack("音量改變了");   CallCallBack("音量大于20", &volume);   }  }   void DecreaseVolume(int v) //降低音量成員函數(shù)   {   volume -= v;   if(volume < 5){ //“音量小于5”事件發(fā)生了   //調(diào)用注冊在兩事件上的回調(diào)函數(shù)  CallCallBack("音量改變了");  CallCallBack("音量小于5", &volume);  }   }   };   //“耳朵”類    class Ear : public CallBack   {   public:  static void Response(CallData callData) //對“音量改變”的反應(yīng)  {   cout<<"音量改變了."<<endl;  }   void HighVoiceResponse(CallData callData)//對高音的反應(yīng)   {   cout<<”喂!太吵了!現(xiàn)在音量是:"<<*((int *)callData)<<endl;  }   void LowVoiceResponse(CallData callData)// 對低音的反應(yīng)   {   cout<<"??!我聽不清了?,F(xiàn)在音量是:"<<*((int *)callData)<<endl;  }   };   void main(void)    {  Speaker s(10); //現(xiàn)在音量為10  Ear e;   //為事件對象s注冊回調(diào)函數(shù)  s.AddCallBack("音量大于20”,(CallBackFunction)&Ear::HighVoiceResponse,&e);  s.AddCallBack("音量小于5”,(CallBackFunction)&Ear::LowVoiceResponse,&e);  s.AddCallBack("音量改變了",(CallBackStaticFunction)&Ear::Response);  s.IncreaseVolume(12);//將音量增加12,現(xiàn)在音量位22  s.DecreaseVolume(20);//將音量減少20,現(xiàn)在音量位2   }

運(yùn)行結(jié)果:

音量改變了.

喂!太吵了!現(xiàn)在音量是:22

音量改變了.

啊!我聽不清了。現(xiàn)在音量是:2

在上例中,揚(yáng)聲器對象s為事件對象,耳朵對象e為回調(diào)對象。。s上被注冊了三個(gè)事件:“音量改變了”,“音量大于20”,“音量小于5”。 回調(diào)函數(shù)分別為:Ear::Response, Ear::HighVoiceResponse,Ear::LowVoiceResponse。當(dāng)揚(yáng)聲器s通過其成員函數(shù)IncreaseVolume和 DecreaseVolume改變音量時(shí),回調(diào)對象e會(huì)自動(dòng)作出反應(yīng)。可見,通過使用CallBack類,在對象間建立消息連接已變?yōu)橐豁?xiàng)很簡單和優(yōu)美的工作。

附:程序清單(本程序在MS VC++5.0和TC++3.0上均編譯通過)

//回調(diào)類的類結(jié)構(gòu):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;//回調(diào)數(shù)據(jù)指針類型定義   typedef void (CallBack::*CallBackFunction)(CallData); //指向回調(diào)成員函數(shù)的指針   typedef void (*CallBackStaticFunction)(CallData); //指向靜態(tài)成員函數(shù)或普通函數(shù)的指針類型定義   class EventRecord{    private:   char *eventName; //回調(diào)事件名稱   CallBack *pointerToCBO;//指向回調(diào)對象的指針   //指向成員函數(shù)的指針和指向靜態(tài)成員函數(shù)(或普通函數(shù))指針的共用體   union{   CallBackFunction pointerToCBF;   CallBackStaticFunction pointerToCBSF;   };   public:   EventRecord(void); //事件記錄類的缺省構(gòu)造函數(shù)   //構(gòu)造包含成員函數(shù)的事件記錄   EventRecord(char *ename,CallBack *pCBO,CallBackFunction pCBF);   //構(gòu)造包含靜態(tài)成員函數(shù)或普通函數(shù)的事件記錄   EventRecord(char *ename,CallBackStaticFunction pCBSF);   ~EventRecord(void);//析構(gòu)事件記錄   void operator = (const EventRecord& er);//重載賦值運(yùn)算符   //判斷當(dāng)前事件記錄的事件名是否為ename   int operator == (char *ename) const;   //判斷當(dāng)前事件記錄是否和指定事件記錄相等   int operator == (const EventRecord& er) const;   void Flush(void); //將當(dāng)前事件記錄清空   int IsEmpty(void) const;//判斷事件記錄是否為空(即事件名是否為空)   friend class CallBack; //讓CallBack類能訪問EventRecord的私有成員;   };   class CallBack {    private:   EventRecord *callBackList; //回調(diào)事件表   int curpos; //當(dāng)前事件記錄位置   int lastpos; //回調(diào)表中***一空閑位置   int size; //回調(diào)表的大小   void MoveFirst(void) { curpos = 0; }//將當(dāng)前記錄置為***條記錄   void MoveNext(void) //將下一條記錄置為當(dāng)前記錄   {   if(curpos == lastpos) return;   curpos++;   }   //判斷回調(diào)表是否被遍歷完    int EndOfList(void) const { return curpos == lastpos; }   public:   CallBack(void);//構(gòu)造函數(shù)   CallBack(const CallBack& cb);//拷貝構(gòu)造函數(shù)   ~CallBack(void);//析構(gòu)函數(shù)   void operator = (const CallBack& cb);// 重載賦值運(yùn)算符   //將回調(diào)對象的成員函數(shù)、靜態(tài)成員函數(shù)(或普通函數(shù))   //注冊為事件對象的回調(diào)函數(shù)   void AddCallBack(char *event,CallBackFunction cbf,CallBack *p);   void AddCallBack(char *event,CallBackStaticFunction cbsf);   //刪除注冊在指定事件上的回調(diào)函數(shù)   void RemoveCallBack(char *event,CallBackFunction cbf,CallBack *p);   void RemoveCallBack(char *event,CallBackStaticFunction cbsf);   void RemoveCallBack(char *event);// 刪除某事件的全部記錄   //執(zhí)行注冊在某一事件上的所有回調(diào)函數(shù)   void CallCallBack(char *event, CallData calldata = NULL);   };   #endif   //回調(diào)類的實(shí)現(xiàn):callback.cpp    #include"callback.h"    //EventRecord類的實(shí)現(xiàn)   EventRecord::EventRecord(void)   {   eventName = NULL;   pointerToCBO = NULL;   //因?yàn)閟izeof(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)    {   if(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和eventname不能交換位置*/  &&(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類的實(shí)現(xiàn)    CallBack::CallBack(void)   {   //按初始尺寸為回調(diào)表分配內(nèi)存空間   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);   }   //一一復(fù)制各條事件記錄   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;//刪除舊的回調(diào)表   callBackList = new EventRecord[size];//重新分配內(nèi)存空間   if(!callBackList){   cerr<<"CallBack: memory allocation error."<<endl;   exit(1);   }   //一一復(fù)制各條事件記錄   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)    {   //如事件名為空,退出   if( (event == NULL)?1:(strlen(event) == 0)) return;   //尋找因刪除事件記錄而產(chǎn)生的***個(gè)空閑位置,并填寫新事件記錄   for(int start=0;start<lastpos;start++)   if(callBackList[start].IsEmpty()){   callBackList[start] = EventRecord(event,pCBO,pCBF);   break;   }   if(start < lastpos) return; //確實(shí)存在空閑位置   //沒有空閑位置,在回調(diào)表后追加新記錄   if(lastpos == size) //回調(diào)表已滿,需“伸長”   {   EventRecord *tempList = callBackList;//暫存舊回調(diào)表指針   //以一定的步長“伸長”回調(diào)表   callBackList = new EventRecord[size + CALLBACKLIST_INCREMENT];   if(!callBackList){   cerr<<"CallBack: memory allocation error."<<endl;   exit(1);   }   //復(fù)制舊回調(diào)表中的記錄   for(int i = 0; i < size; i++) callBackList[i] = tempList[i];   delete [] tempList;//刪除舊回調(diào)表   size += CALLBACKLIST_INCREMENT;//記下新回調(diào)表的尺寸   }   //構(gòu)造新的事件記錄并將其填入回調(diào)表中   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<lastpos;start++)   if(callBackList[start].IsEmpty()){   callBackList[start] = EventRecord(event,pCBSF);   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,pCBSF);   lastpos++;   }   //刪除注冊在指定事件上的成員函數(shù)   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();   }   //刪除注冊在指定事件上的靜態(tài)成員函數(shù)或普通函數(shù)   void CallBack::RemoveCallBack(char *event,CallBackStaticFunction pCBSF)   {   if( (event == NULL)?1:(strlen(event) == 0)) return;   EventRecord er(event,pCBSF);    for(int i = 0; i < lastpos; i++)   if(callBackList[i] == er) callBackList[i].Flush();   }   //刪除注冊在指定事件上的所有回調(diào)函數(shù)   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 callData)   {   if( (event == NULL)?1:(strlen(event) == 0)) return;    CallBack *pCBO;   CallBackFunction pCBF;   CallBackStaticFunction pCBSF;   MoveFirst();   while(!EndOfList())   {   //如當(dāng)前事件記錄和指定事件不匹配,轉(zhuǎn)入下一條記錄繼續(xù)循環(huán)   if(!(callBackList[curpos] == event))   {   MoveNext();   continue;   }   //如找到匹配記錄   pCBO = callBackList[curpos].pointerToCBO;   //如事件記錄中回調(diào)對象指針為空,說明該記錄中保存的是靜態(tài)函數(shù)指針   if(pCBO == NULL){   pCBSF = callBackList[curpos].pointerToCBSF;   pCBSF(callData);//調(diào)用該靜態(tài)回調(diào)函數(shù)   }   else //如事件記錄中回調(diào)對象指針非空,說明該記錄中保存的是成員函數(shù)指針   {   pCBF = callBackList[curpos].pointerToCBF;   (pCBO->*pCBF)(callData);// 調(diào)用該回調(diào)對象的成員函數(shù)   }   MoveNext();   }   }

到此,相信大家對“C++程序設(shè)計(jì)如何建立對象間消息連接”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

c++
AI