激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C/C++ - C++中事件機制的簡潔實現及需要放棄的特性

C++中事件機制的簡潔實現及需要放棄的特性

2020-11-17 12:08C++教程網 C/C++

事件模型是被廣泛使用的好東西,但是C++標準庫里沒有現成的,現在VC11可以用在XP下了,那么就痛快的拿起C++11提供的先進設施組合出一個輕便的實現吧感興趣的朋友可以了解下,或許對你有所幫助

事件模型是被廣泛使用的好東西,但是C++標準庫里沒有現成的,其他實現又復雜或者不優雅,比如需要使用宏。現在VC11可以用在XP下了,那么就痛快的拿起C++11提供的先進設施組合出一個輕便的實現吧。

為了達到簡潔的目的,需要放棄一些特性
1、不支持判斷函數是否已經綁定過(因為std::function不提供比較方法,自己實現function的話代碼又變多了)
2、需要使用者接收返回的回調函數標識來移除事件綁定(原因同上)
3、事件沒有返回值,不支持回調函數優先級、條件回調等事件高級特性(比如返回所有處理結果中的最大最小值;只回調與指定參數匹配的事件處理函數)
4、事件參數理論上無限,實際上有限,一般支持0~10個參數(VC11還沒有支持變長模板參數,GCC有了。不過可以通過缺省模板參數和偏特化來模擬,所以理論上無限制)
5、不是線程安全的

:3、5兩條可以通過引入策略模式來提供靈活支持,就像標準庫和Loki做的那樣,實現一個完整的事件機制。

最簡單的實現

復制代碼 代碼如下:


#include <map>
#include <functional>
using namespace std;
template<class Param1, class Param2>
class Event
{
typedef void HandlerT(Param1, Param2);
int m_handlerId;
public:
Event() : m_handlerId(0) {}
template<class FuncT> int addHandler(FuncT func)
{
m_handlers.emplace(m_handlerId, forward<FuncT>(func));
return m_handlerId++;
}
void removeHandler(int handlerId)
{
m_handlers.erase(handlerId);
}
void operator ()(Param1 arg1, Param2 arg2)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2);
}
private:
map<int, function<HandlerT>> m_handlers;
};


addHandler把回調函數完美轉發給std::function,讓標準庫來搞定各種重載,然后返回一個標識符用來注銷綁定。試一下,工作的不錯:

復制代碼 代碼如下:


void f1(int, int)
{
puts("f1()");
}
struct F2
{
void f(int, int)
{
puts("f2()");
}
void operator ()(int, int)
{
puts("f3()");
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Event<int, int> e;
int id = e.addHandler(f1);
e.removeHandler(id);
using namespace std::placeholders;
F2 f2;
e.addHandler(bind(&F2::f, f2, _1, _2));
e.addHandler(bind(f2, _1, _2));
e.addHandler([](int, int) {
puts("f4()");
});
e(1, 2);
return 0;
}


雖然這里有一個小小的缺點,對于仿函數,如果想使用它的指針或引用是不可以直接綁定的,需要這樣做:

復制代碼 代碼如下:


e.addHandler(ref(f2));
e.addHandler(ref(*pf2)); // pf2是指向f2的指針 但是使用仿函數對象指針的情形不多,也不差多敲幾個


字符,何況在有Lambda表達式的情況下呢?
改進
1、有人不喜歡bind,用起來麻煩,放到addhandler里面去:

復制代碼 代碼如下:


template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2));
return m_handlerId++;
}


2、擴展參數個數。沒有變長模板參數,變通一下:

復制代碼 代碼如下:


struct NullType {};
template<class P1 = Private::NullType, class P2 = Private::NullType>
class Event
{
public:
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2);
}
};
template<>
class Event<Private::NullType, Private::NullType>
{
public:
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj)));
return m_handlerId++;
}
void operator ()()
{
for ( const auto& i : m_handlers )
i.second();
}
};
template<class P1>
class Event<P1, Private::NullType>
{
public:
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1));
return m_handlerId++;
}
void operator ()(P1 arg1)
{
for ( const auto& i : m_handlers )
i.second(arg1);
}
};


現在支持0~2個參數了。注意到各個模板里有公共代碼,提取出來放進基類,然后要做的就是打開文本生成器了
完整代碼
代碼下載

復制代碼 代碼如下:


View Code
#pragma once
#include <map>
#include <functional>
namespace Utility
{
namespace Private
{
struct NullType {};
template<class HandlerT>
class EventBase
{
public:
EventBase() : m_handlerId(0) {}
template<class FuncT> int addHandler(FuncT func)
{
m_handlers.emplace(m_handlerId, std::forward<FuncT>(func));
return m_handlerId++;
}
void removeHandler(int handlerId)
{
m_handlers.erase(handlerId);
}
protected:
int m_handlerId;
std::map<int, std::function<HandlerT>> m_handlers;
};
}
template<class P1 = Private::NullType, class P2 = Private::NullType, class P3 = Private::NullType, class P4 = Private::NullType, class P5 = Private::NullType, class P6 = Private::NullType, class P7 = Private::NullType, class P8 = Private::NullType, class P9 = Private::NullType, class P10 = Private::NullType>
class Event
: public Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7, _8, _9, _10));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7, P8 arg8, P9 arg9, P10 arg10)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
}
};
template<>
class Event<Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void ()>
{
public:
using Private::EventBase<void ()>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT const obj, FuncT func)
{
m_handlers.emplace(m_handlerId, std::bind(func, obj));
return m_handlerId++;
}
void operator ()()
{
for ( const auto& i : m_handlers )
i.second();
}
};
template<class P1>
class Event<P1, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1)>
{
public:
using Private::EventBase<void (P1)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1));
return m_handlerId++;
}
void operator ()(P1 arg1)
{
for ( const auto& i : m_handlers )
i.second(arg1);
}
};
template<class P1, class P2>
class Event<P1, P2, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2)>
{
public:
using Private::EventBase<void (P1, P2)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2);
}
};
template<class P1, class P2, class P3>
class Event<P1, P2, P3, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2, P3)>
{
public:
using Private::EventBase<void (P1, P2, P3)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3);
}
};
template<class P1, class P2, class P3, class P4>
class Event<P1, P2, P3, P4, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2, P3, P4)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4);
}
};
template<class P1, class P2, class P3, class P4, class P5>
class Event<P1, P2, P3, P4, P5, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2, P3, P4, P5)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4, P5)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4, _5));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4, arg5);
}
};
template<class P1, class P2, class P3, class P4, class P5, class P6>
class Event<P1, P2, P3, P4, P5, P6, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2, P3, P4, P5, P6)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4, P5, P6)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4, arg5, arg6);
}
};
template<class P1, class P2, class P3, class P4, class P5, class P6, class P7>
class Event<P1, P2, P3, P4, P5, P6, P7, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
};
template<class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
class Event<P1, P2, P3, P4, P5, P6, P7, P8, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7, P8)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7, P8)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7, _8));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7, P8 arg8)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
}
};
template<class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>
class Event<P1, P2, P3, P4, P5, P6, P7, P8, P9, Private::NullType>
: public Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7, P8, P9)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7, P8, P9)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7, _8, _9));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7, P8 arg8, P9 arg9)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
}
};
} // namespace Utility


測試代碼
各種綁定方式

復制代碼 代碼如下:


View Code
#include "Event.h"
using namespace std;
void f1(int, int)
{
puts("f1()");
}
struct F2
{
F2() { puts("F2 construct"); }
F2(const F2 &) { puts("F2 copy"); }
F2(F2 &&) { puts("F2 move"); }
F2& operator=(const F2 &) { puts("F2 copy assign"); return *this; }
F2& operator=(F2 &&) { puts("F2 move assign"); return *this; }
void f(int, int)
{
puts("f2()");
}
void fc(int, int) const
{
puts("f2c()");
}
};
struct F3
{
F3() { puts("F3 construct"); }
F3(const F3 &) { puts("F3 copy"); }
F3(F3 &&) { puts("F3 move"); }
F3& operator=(const F3 &) { puts("F3 copy assign"); return *this; }
F3& operator=(F3 &&) { puts("F3 move assign"); return *this; }
void operator ()(int, int) const
{
puts("f3()");
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Utility::Event<int, int> e;
// 一般函數
e.addHandler(f1);
int id = e.addHandler(&f1);
e.removeHandler(id); // 移除事件處理函數
// 成員函數
using namespace std::placeholders;
F2 f2;
const F2 *pf2 = &f2;
e.addHandler(bind(&F2::f, &f2, _1, _2)); // std::bind
e.addHandler(&f2, &F2::f);
e.addHandler(pf2, &F2::fc); // 常量指針
puts("----addHandler(f2, &F2::f)----");
e.addHandler(f2, &F2::f); // 對象拷貝構造
puts("----addHandler(F2(), &F2::f)----");
e.addHandler(F2(), &F2::f); // 對象轉移構造
puts("--------");
// 仿函數
F3 f3;
const F3 *pf3 = &f3;
puts("----addHandler(f3)----");
e.addHandler(f3); // 對象拷貝構造
puts("----addHandler(F3())----");
e.addHandler(F3()); // 對象轉移構造
puts("--------");
e.addHandler(ref(f3)); // 引用仿函數對象
e.addHandler(ref(*pf3)); // 引用仿函數常量對象
puts("--------");
// Lambda表達式
e.addHandler([](int, int) {
puts("f4()");
});
// 激發事件
e(1, 2);
return 0;
}

延伸 · 閱讀

精彩推薦
  • C/C++C語言實現電腦關機程序

    C語言實現電腦關機程序

    這篇文章主要為大家詳細介紹了C語言實現電腦關機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
  • C/C++C/C++經典實例之模擬計算器示例代碼

    C/C++經典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關于C/C++經典實例之模擬計算器的相關資料,文中通過示...

    jia150610152021-06-07
  • C/C++深入理解goto語句的替代實現方式分析

    深入理解goto語句的替代實現方式分析

    本篇文章是對goto語句的替代實現方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網7342020-12-03
  • C/C++c++ 單線程實現同時監聽多個端口

    c++ 單線程實現同時監聽多個端口

    這篇文章主要介紹了c++ 單線程實現同時監聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下...

    青山的青6062022-01-04
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內存中的數據都是暫時的,當程序結束時,它們都將丟失,為了永久性的保存大量的數據,C語言提供了對文件的操作,這篇文章主要給大家介紹了關于C語言中文件...

    針眼_6702022-01-24
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數使用

    詳解c語言中的 strcpy和strncpy字符串函數使用

    strcpy 和strcnpy函數是字符串復制函數。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
  • C/C++學習C++編程的必備軟件

    學習C++編程的必備軟件

    本文給大家分享的是作者在學習使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: 久久国产一二三 | 国产成人精品自拍视频 | 一级黄色毛片播放 | 亚洲一级毛片 | 99日韩精品视频 | 日本高清电影在线播放 | 久久成人免费观看 | 久久久久久麻豆 | 毛片av网| 视频www | 精品一区二区免费视频视频 | 精品一区二区三区在线观看国产 | av播放在线| 蜜桃网站在线观看 | 亚洲精品成人悠悠色影视 | 亚洲天堂在线电影 | 欧美精品一区二区三区久久久 | 黄色大片网站在线观看 | 久在线播放 | 污片视频网站 | 久久69精品久久久久久国产越南 | 色播亚洲| 亚洲第一激情网 | 一级大片一级一大片 | 手机国产乱子伦精品视频 | 多男操一女视频 | 久久99精品国产自在现线 | 羞羞答答tv | 欧美性生活区 | 欧美有码在线观看 | 久久99久久99免费视频 | avlululu | 天天色狠狠干 | 又黄又爽免费无遮挡在线观看 | 成人午夜免费福利 | 亚洲影视中文字幕 | 久久九九热re6这里有精品 | 黄色av网站在线观看 | 久久亚洲春色中文字幕久久 | 免费毛片观看 | 一级电影在线观看 |