科技时代新浪首页 > 科技时代 > 软件 > 正文

C++中建立对象间消息连接的系统方法(4)


http://www.sina.com.cn 2005年02月23日 10:10 天极yesky

  文/项飞

  附:程序清单(本程序在MS VC++5.0和TC++3.0上均编译通过)

file://回调类的类结构: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;//回调数据指针类型定义

typedef void (CallBack::*CallBackFunction)(CallData); file://指向回调成员函数的指针

typedef void (*CallBackStaticFunction)(CallData); file://指向静态成员函数或普通函数的指针类型定义

class EventRecord{
 private:
  char *eventName; file://回调事件名称
  CallBack *pointerToCBO;//指向回调对象的指针
  file://指向成员函数的指针和指向静态成员函数(或普通函数)指针的共用体
  union{
   CallBackFunction pointerToCBF;
   CallBackStaticFunction pointerToCBSF;
  };
 public:
  EventRecord(void); file://事件记录类的缺省构造函数
  file://构造包含成员函数的事件记录
  EventRecord(char *ename,CallBack *pCBO,CallBackFunction pCBF);
  file://构造包含静态成员函数或普通函数的事件记录
  EventRecord(char *ename,CallBackStaticFunction pCBSF);
  ~EventRecord(void);//析构事件记录
  void operator = (const EventRecord& er);//重载赋值运算符
  file://判断当前事件记录的事件名是否为ename

  int operator == (char *ename) const;

  file://判断当前事件记录是否和指定事件记录相等

  int operator == (const EventRecord& er) const;

  void Flush(void); file://将当前事件记录清空

  int IsEmpty(void) const;//判断事件记录是否为空(即事件名是否为空)

  friend class CallBack; file://让CallBack类能访问EventRecord的私有成员;

};

class CallBack {
 private:
  EventRecord *callBackList; file://回调事件表
  int curpos; file://当前事件记录位置
  int lastpos; file://回调表中最后一空闲位置
  int size; file://回调表的大小

  void MoveFirst(void) { curpos = 0; }//将当前记录置为第一条记录
  void MoveNext(void) file://将下一条记录置为当前记录
  {
   if(curpos == lastpos) return;
   curpos++;
  }

  file://判断回调表是否被遍历完

  int EndOfList(void) const { return curpos == lastpos; }
   public:
    CallBack(void);//构造函数
    CallBack(const CallBack& cb);//拷贝构造函数
    ~CallBack(void);//析构函数

  void operator = (const CallBack& cb);// 重载赋值运算符

  file://将回调对象的成员函数、静态成员函数(或普通函数) file://注册为事件对象的回调函数

  void AddCallBack(char *event,CallBackFunction cbf,CallBack *p);
  void AddCallBack(char *event,CallBackStaticFunction cbsf);
  file://删除注册在指定事件上的回调函数

  void RemoveCallBack(char *event,CallBackFunction cbf,CallBack *p);
  void RemoveCallBack(char *event,CallBackStaticFunction cbsf);
  void RemoveCallBack(char *event);// 删除某事件的全部记录

  file://执行注册在某一事件上的所有回调函数

  void CallCallBack(char *event, CallData calldata = NULL);

 };

 #endif

 file://回调类的实现:callback.cpp

 #include"callback.h"

 file://EventRecord类的实现

 EventRecord::EventRecord(void)
 {
  eventName = NULL;
  pointerToCBO = NULL;
  file://因为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)
 {
  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;
 }

 file://Callback类的实现
 CallBack::CallBack(void)
 {
  file://按初始尺寸为回调表分配内存空间

  callBackList = new EventRecord[CALLBACKLIST_INIT_SIZE];

  if(!callBackList){
   cerr<<"CallBack: memory allocation error."<   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."<   exit(1);
  }
  file://一一复制各条事件记录
  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;//删除旧的回调表
  callBackList = new EventRecord[size];//重新分配内存空间
  if(!callBackList){
   cerr<<"CallBack: memory allocation error."<   exit(1);
  }

  file://一一复制各条事件记录

  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)
 {
  file://如事件名为空,退出
  if( (event == NULL)?1:(strlen(event) == 0)) return;
  file://寻找因删除事件记录而产生的第一个空闲位置,并填写新事件记录
  for(int start=0;start   if(callBackList[start].IsEmpty()){
    callBackList[start] = EventRecord(event,pCBO,pCBF);
    break;
   }
   if(start < lastpos) return; file://确实存在空闲位置
   file://没有空闲位置,在回调表后追加新记录
   if(lastpos == size) file://回调表已满,需“伸长”
   {
    EventRecord *tempList = callBackList;//暂存旧回调表指针
    file://以一定的步长“伸长”回调表
    callBackList = new EventRecord[size + CALLBACKLIST_INCREMENT];
    if(!callBackList){
     cerr<<"CallBack: memory allocation error."<     exit(1);
    }
    file://复制旧回调表中的记录
    for(int i = 0; i < size; i++) callBackList[i] = tempList[i];
    delete [] tempList;//删除旧回调表
    size += CALLBACKLIST_INCREMENT;//记下新回调表的尺寸
   }
   file://构造新的事件记录并将其填入回调表中
   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 < lastpos) return; file://a hole is found
   if(lastpos == size) file://event list is insufficient
   {
    EventRecord *tempList = callBackList;
    callBackList = new EventRecord[size + CALLBACKLIST_INCREMENT];

    if(!callBackList){
     cerr<<"CallBack: memory allocation error."<     exit(1);
    }
    for(int i = 0; i < size; i++) callBackList[i] = tempList[i];
    delete [] tempList;
    size += CALLBACKLIST_INCREMENT;
   }

  callBackList[lastpos] = EventRecord(event,pCBSF);
  lastpos++;
 }

 file://删除注册在指定事件上的成员函数

 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();
 }

 file://删除注册在指定事件上的静态成员函数或普通函数

 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();
 }

 file://删除注册在指定事件上的所有回调函数

 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())
  {
   file://如当前事件记录和指定事件不匹配,转入下一条记录继续循环
   if(!(callBackList[curpos] == event))
   {
    MoveNext();
    continue;
   }
   file://如找到匹配记录
   pCBO = callBackList[curpos].pointerToCBO;
   file://如事件记录中回调对象指针为空,说明该记录中保存的是静态函数指针
   if(pCBO == NULL){
    pCBSF = callBackList[curpos].pointerToCBSF;
    pCBSF(callData);//调用该静态回调函数
   }
   else file://如事件记录中回调对象指针非空,说明该记录中保存的是成员函数指针
   {
    pCBF = callBackList[curpos].pointerToCBF;
    (pCBO->*pCBF)(callData);// 调用该回调对象的成员函数
   }
   MoveNext();
  }
 }

[上一页]  [1]  [2]  [3]  [4]


  点击此处查询全部C++新闻

评论】【应用软件】【推荐】【 】【打印】【下载点点通】【关闭
 

 
新 闻 查 询
关键词



彩 信 专 题
东方美女
迷人风情性感姿态
金鸡送福
恭喜发财图铃拿来
请输入歌曲/歌手名:
更多专题   更多彩信
 
 



科技时代意见反馈留言板 电话:010-82628888-5828   欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

Copyright © 1996 - 2005 SINA Inc. All Rights Reserved

版权所有 新浪网