日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++中的事件分发

發(fā)布時間:2025/6/17 c/c++ 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++中的事件分发 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

  本文意在展現(xiàn)一個C++實現(xiàn)的通用事件分發(fā)系統(tǒng),能夠靈活的處理各種事件。對于事件處理函數(shù)的注冊,希望既能注冊到普通函數(shù),注冊到事件處理類,也能注冊到任意類的成員函數(shù)。這樣在游戲客戶端的邏輯處理中,可以非常靈活的處理事件,讓普通函數(shù)和類的成員函數(shù)既能手動調(diào)用,又能作為事件響應函數(shù)。

  游戲是一個交互很強的軟件。在客戶端中,事件充斥于整個程序的各個角落,玩家操作事件,網(wǎng)絡消息事件,音頻事件,定時事件等等。這些事件通常參數(shù)不一致,分屬不同系統(tǒng),使得消息的處理非常離散,分布于各個UI和系統(tǒng)類中。這使得在設計事件分發(fā)系統(tǒng)的時候,需要充分考慮通用性,能夠適應各種處理函數(shù)需求。服務器在處理網(wǎng)絡和數(shù)據(jù)庫消息時,雖然通常是固定的處理格式,但同樣需要實現(xiàn)一個統(tǒng)一的事件分發(fā)的機制。客戶端C#有delegate的存在,因此可以非常方便的將成員函數(shù)綁定到delegate進行調(diào)用。在unity項目中,利用C#的這一特性,非常容易搭起事件系統(tǒng)框架。但是,C++項目由于常常有成員函數(shù)和普通函數(shù)并存,因此事件分發(fā)時,需要考慮到兩種情況。

  本文實現(xiàn)的事件分發(fā)系統(tǒng)是一個集中注冊和分發(fā)的系統(tǒng)。消息的注冊和分發(fā)都由EventManager單例負責,如果需要,可以在EventManager中加入EventQueue實現(xiàn)事件隊列,進而緩存消息,異步分發(fā)。以下為EventManager類實現(xiàn)。

1 #ifndef EVENTMANAGER_H 2 #define EVENTMANAGER_H 3 enum EventId 4 { 5 EVT_TICK = 0, 6 }; 7 8 struct Event 9 { 10 Event(int id) : id_(id) 11 {} 12 ~Event() 13 {} 14 int id_; 15 //params 16 }; 17 18 class EventHandler 19 { 20 public: 21 virtual int HandleEvent(Event *evt) 22 { 23 return 0; 24 } 25 }; 26 27 class EventManager 28 { 29 public: 30 typedef std::list<EventHandler *> HandlerList; 31 typedef std::map<int, HandlerList> IdHandlerMap; 32 33 public: 34 static EventManager &Instance() 35 { 36 static EventManager inst_; 37 return inst_; 38 } 39 40 void AddEventHandler(int id, EventHandler *handler) 41 { 42 if (handler == NULL) 43 return; 44 auto pair = handler_map_.insert(std::make_pair(id, HandlerList())); 45 auto it = pair.first; 46 if (it == handler_map_.end()) 47 return; 48 it->second.push_back(handler); 49 } 50 51 void RemoveEventHandler(int id, EventHandler *handler) 52 { 53 if (handler == NULL) 54 return; 55 auto it = handler_map_.find(id); 56 if (it == handler_map_.end()) 57 return; 58 auto listIt = std::find(it->second.begin(), it->second.end(), handler); 59 if (listIt != it->second.end()) 60 it->second.erase(listIt); 61 } 62 63 void ClearEventHandler(int id) 64 { 65 handler_map_.erase(id); 66 } 67 68 void DispatchEvent(Event *evt) 69 { 70 auto it = handler_map_.find(evt->id_); 71 if (it == handler_map_.end()) 72 return; 73 auto &handler_list = it->second; 74 for (auto listIt = handler_list.begin(); listIt != handler_list.end(); ++listIt) 75 { 76 if ((*listIt) == NULL) continue; 77 (*listIt)->HandleEvent(evt); 78 } 79 } 80 81 private: 82 EventManager(){} 83 EventManager(const EventManager&){} 84 ~EventManager(){} 85 86 IdHandlerMap handler_map_; 87 }; 88 89 #endif

  其中:

  EventId是一個事件類型枚舉,以區(qū)分不同類型的事件,這里我只定義一個用來舉例的時鐘TICK事件。

  Event定義一個具體事件,它作為事件基類,僅有一個事件類型(id)。實際使用的事件類繼承自Event,并添加需要的參數(shù)傳遞給事件處理函數(shù)。

  EventHandler是事件處理基類,當有事件分發(fā)給某個Handler時,它做的就是調(diào)用HandleEvent(注意,這里一種Event可以同時注冊分發(fā)給多個EventHandler依次處理,在客戶端中常常需要將消息分發(fā)到多個地方處理)。

  EventManager是集中的事件管理器,這里作為示例用簡單單例實現(xiàn),可以根據(jù)需求擴展。它只有一個成員變量,EventId到它的EventHandler列表的映射。主要功能:注冊,解注冊Handler和分發(fā)事件。

?

  使用時,定義具體的Event類型和處理類,注冊事件處理函數(shù),分發(fā)事件即可。這里用TickEvent作為例子。

1 #include "EventManager.h" 2 3 struct TickEvent : Event 4 { 5 TickEvent() : Event(EVT_TICK), time_(0) 6 {} 7 ~TickEvent() 8 {} 9 time_t time_; 10 }; 11 12 class TimeEventHandler : public EventHandler 13 { 14 virtual int HandleEvent(Event *evt) 15 { 16 TickEvent *tickEvt = (TickEvent*)evt; 17 printf("time now: %d", (int)tickEvt->time_); 18 return 0; 19 } 20 }; 21 22 TickEvent tickEvt; 23 TimeEventHandler timeHandler; 24 EventManager::Instance().AddEventHandler(EVT_TICK, &timeHandler); 25 EventManager::Instance().DispatchEvent(&tickEvt); 26 EventManager::Instance().RemoveEventHandler(EVT_TICK, &timeHandler);

  TimeEventHandler作為EVT_TICK事件的處理器,在HandleEvent中做相應的處理。

  這里是一個專門的事件處理器類,那么普通類的成員函數(shù)中如何方便的處理相應的消息呢?如果每個需要處理消息的類都需要繼承自TimeEventHandler并且實現(xiàn)一個HandleEvent,那么勢必會有局限性,如不能響應多個消息、須多重繼承。如果能直接注冊成員函數(shù),那真是太好了!

  我們來看一個例子,一個UIClass類,OnEvent正是一個處理TICK事件的函數(shù)。我們當然可以額外定義一個普通函數(shù)作為響應回調(diào),讓特定的EventHandler持有對象,并調(diào)用該普通函數(shù),在普通函數(shù)中再調(diào)用對象的成員函數(shù)。但是這樣做勢必使得整個項目的代碼很冗余。

1 template<class Type> 2 class ClassEventHandler : public EventHandler 3 { 4 public: 5 typedef int (Type::*HandlerFunc)(Event *evt); 6 7 public: 8 ClassEventHandler(Type *ptr, HandlerFunc func): 9 pointer_(ptr), 10 func_(func) 11 { 12 } 13 virtual int HandleEvent(Event *evt) 14 { 15 if (pointer_ && func_) 16 return (pointer_->*func_)(evt); 17 return 0; 18 } 19 private: 20 Type *pointer_; 21 HandlerFunc func_; 22 }; 23 //test eventmanager 24 class UIClass 25 { 26 public: 27 UIClass() 28 { 29 } 30 31 ~UIClass() 32 { 33 } 34 35 int OnEvent(Event *evt) 36 { 37 TickEvent *tickEvt = (TickEvent*)evt; 38 printf("uiclass event, time now: %d", (int)tickEvt->time_); 39 return 0; 40 } 41 }; 42 43 UIClass ui; 44 ClassEventHandler<UIClass> evthandler(&ui, &UIClass::OnEvent); 45 EventManager::Instance().AddEventHandler(EVT_TICK, &evthandler); 46 EventManager::Instance().DispatchEvent(&tickEvt); 47 EventManager::Instance().RemoveEventHandler(EVT_TICK, &evthandler);

  如上定義一個處理類模板ClassEventHandler,繼承自EventHandler,有兩個成員變量,持有對象和對象的類成員函數(shù),handler初始化時指定相應的對象和成員函數(shù),HandleEvent時調(diào)用該成員函數(shù)。如此使用時,除了多一個類模板特例化,幾乎不帶來任何額外代碼成本,不需要對UIClass做任何特殊處理,這正是我們想要看到的~

  補上一個實例圖,能夠更簡單的說明一個Event的處理過程:

  如上,每個Event有一個特定的EventId,當有Event發(fā)送給EventManager處理時,根據(jù)EventId索引到相應的EventHandler的列表,借助EventHandler的模板,這些Handler既可以時一般函數(shù),也可以是成員函數(shù)。

  事件分發(fā)系統(tǒng)的實現(xiàn)有多種,也有一些是預先注冊好相應的事件內(nèi)容,分發(fā)時直接分發(fā)事件id等方式。私以為這種傳遞Event指針的方式是最靈活和通用的,可以傳遞任意消息,甚至可以實現(xiàn)消息的嵌套,遞歸傳遞消息。在客戶端和服務器都能有一致的應用,這對于后期想共用前后端代碼是很有好處的。

?

轉載于:https://www.cnblogs.com/kevonyang/p/5965825.html

《新程序員》:云原生和全面數(shù)字化實踐50位技術專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的C++中的事件分发的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美成人精品欧美一级 | 青青草草 | 亚洲情在线 | 亚洲欧美激情在线 | 少妇人妻一区二区 | 免费看久久 | 香蕉国产| 精品国模一区二区三区 | 理论片在线观看理伦片 | 91黄色免费网站 | 欧美在线观看视频 | 97超碰在线资源 | 国产美女被草 | 人体内射精一区二区三区 | 看全色黄大色黄大片女一次牛 | 亚洲一久久 | 日韩永久免费视频 | 美女扒开让男人桶爽 | 欧美日韩不卡在线 | 中国女人裸体乱淫 | 久色在线| 欧美日韩国语 | 国产精品国语 | 亚洲自拍偷拍网站 | 国产极品网站 | 人人人妻人人澡人人爽欧美一区 | 亚洲一区二区伦理 | 污污内射在线观看一区二区少妇 | 日韩成人在线影院 | 狠狠视频 | 蜜臀久久精品久久久用户群体 | 国产精品aⅴ | 老牛嫩草二区三区观影体验 | 四虎永久免费观看 | 精品视频免费在线 | 欧美成人一区在线 | 呦呦色 | 日本精品入口免费视频 | 成人免费毛片嘿嘿连载 | 色综合天天 | 国产99在线播放 | 久久精品日韩无码 | 日本欧美一区二区三区不卡视频 | 日本三级精品 | 北条麻妃久久精品 | 麻豆自拍视频 | 国产黄色免费网站 | 爱草在线视频 | 免费不卡av| 国产黄色一级 | 国产又色又爽无遮挡免费 | www色天使 | 在线中文字幕日韩 | 在线观看1区 | 69国产精品 | 欧美午夜性 | 欧美视频直播网站 | 日韩av无码一区二区三区 | 欧美做爰全过程免费看 | 欧美另类精品 | 亚洲国产激情 | 93久久精品日日躁夜夜躁欧美 | 伊人射 | 日本三级中文字幕在线观看 | 香蕉爱视频 | 夜夜嗨一区二区三区 | 老师的肉丝玉足夹茎 | 久久精品人妻av一区二区三区 | 日韩国产在线 | 国产福利91 | 欧美不卡一区 | 日日噜噜噜夜夜爽爽狠狠 | 淫五月| 特级新鲜大片片 | 嫩草影院懂你的 | 日韩91视频| 欧美精品一区二区三区四区五区 | 午夜偷拍视频 | 三级黄色免费片 | 色噜噜在线观看 | 男人的天堂伊人 | wwwxxx在线 | tube日本69第一次 | 国产精品夜夜夜爽张柏芝 | 激情欧美一区二区免费视频 | 色欲av永久无码精品无码蜜桃 | 97超碰免费观看 | 最近最新中文字幕 | 伊人一级 | 欧美精品免费看 | 欧美亚洲视频一区 | 国产嫩bbwbbw高潮 | 国产精品综合久久 | 亚洲av少妇一区二区在线观看 | 黑帮大佬和我的365日第二部 | 久久久国产视频 | 毛茸茸毛片 | 91精品一区二区三区四区 | 欧美日韩精品综合 |