亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

事件機制在c++中的簡明實現和要拋棄的特性

2020-02-24 14:35:25
字體:
來源:轉載
供稿:網友

事件機制在c++中的簡明實現和要拋棄的特性,事件模型是被廣泛使用的好東西,但是C++標準庫里沒有現成的,現在VC11可以用在XP下了,那么就痛快的拿起C++11提供的先進設施組合出一個輕便的實現吧,感興趣的朋友可以了解下,或許對你有所幫助喔~
為了達到簡潔的目的,需要放棄一些特性
1、不支持判斷函數是否已經綁定過(因為std::function不提供比較方法,自己實現function的話代碼又變多了)
2、需要使用者接收返回的回調函數標識來移除事件綁定(原因同上)
3、事件沒有返回值,不支持回調函數優先級、條件回調等事件高級特性(比如返回所有處理結果中的最大最小值;只回調與指定參數匹配的事件處理函數)
4、事件參數理論上無限,實際上有限,一般支持0~10個參數(VC11還沒有支持變長模板參數,GCC有了。不過可以通過缺省模板參數和偏特化來模擬,所以理論上無限制)
5、不是線程安全的

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

最簡單的實現


#include
#include
using namespace std;
template
class Event
{
typedef void HandlerT(Param1, Param2);
int m_handlerId;
public:
Event() : m_handlerId(0) {}
template int addHandler(FuncT func)
{
m_handlers.emplace(m_handlerId, forward(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> 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 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 int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward(obj), _1, _2));
return m_handlerId++;
}


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

?

?


struct NullType {};
template
class Event
{
public:
template int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward(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<:nulltype private::nulltype>
{
public:
template int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward(obj)));
return m_handlerId++;
}
void operator ()()
{
for ( const auto& i : m_handlers )
i.second();
}
};
template
class Event
{
public:
template int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward(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
#include
namespace Utility
{
namespace Private
{
struct NullType {};
template
class EventBase
{
public:
EventBase() : m_handlerId(0) {}
template int addHandler(FuncT func)
{
m_handlers.emplace(m_handlerId, std::forward(func));
return m_handlerId++;
}
void removeHandler(int handlerId)
{
m_handlers.erase(handlerId);
}
protected:
int m_handlerId;
std::map> m_handlers;
};
}
template
class Event
: public Private::EventBase
{
public:
using Private::EventBase::addHandler;
template int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward(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<:nulltype private::nulltype>
: public Private::EventBase
{
public:
using Private::EventBase::addHandler;
template 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 Event
: public Private::EventBase
{
public:
using Private::EventBase::addHandler;
template int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward(obj), _1));
return m_handlerId++;
}
void operator ()(P1 arg1)
{
for ( const auto& i : m_handlers )
i.second(arg1);
}
};
template
class Event
: public Private::EventBase
{
public:
using Private::EventBase::addHandler;
template int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward(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
: public Private::EventBase
{
public:
using Private::EventBase::addHandler;
template int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward(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 Event
: public Private::EventBase
{
public:
using Private::EventBase::addHandler;
template int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward(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 Event
: public Private::EventBase
{
public:
using Private::EventBase::addHandler;
template int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward(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 Event
: public Private::EventBase
{
public:
using Private::EventBase::addHandler;
template int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward(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 Event
: public Private::EventBase
{
public:
using Private::EventBase::addHandler;
template int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward(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 Event
: public Private::EventBase
{
public:
using Private::EventBase::addHandler;
template int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward(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 Event
: public Private::EventBase
{
public:
using Private::EventBase::addHandler;
template int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward(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 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++的內容請繼續關注武林技術頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品成人一区二区| 国产亚洲欧美日韩美女| 亚洲国产精品99| 亚洲新中文字幕| 欧美午夜电影在线| 国产精品老牛影院在线观看| 亚洲精品国产免费| 97在线精品国自产拍中文| 久久久爽爽爽美女图片| 欧美日韩国产成人| 国产成人精品国内自产拍免费看| 亚洲sss综合天堂久久| 欧美日韩国产麻豆| 亚洲第一网中文字幕| 亚洲人高潮女人毛茸茸| 一区二区三区精品99久久| 2019中文字幕全在线观看| 色偷偷综合社区| 日韩精品视频三区| 国产一区视频在线播放| 欧美男插女视频| 福利视频导航一区| 国产精品久久久久久久一区探花| 日韩在线高清视频| 中文字幕欧美日韩va免费视频| 精品久久久久久中文字幕大豆网| 久久韩国免费视频| 日日骚av一区| 日本久久久久久久| 91美女片黄在线观| 91精品国产91久久久久福利| 亚洲色图50p| 亚洲色图美腿丝袜| 777午夜精品福利在线观看| 亚洲人成电影网站色www| 精品成人乱色一区二区| 97成人精品视频在线观看| 亚洲一区二区三区四区在线播放| 91精品中文在线| 亚洲国产精品一区二区三区| 国产精品亚洲一区二区三区| 欧美有码在线观看| 精品国产91久久久久久| 一个人看的www久久| 亚洲欧洲视频在线| 亚洲女人被黑人巨大进入al| 日韩国产在线播放| 91香蕉嫩草影院入口| 久久久免费精品视频| 欧美成人午夜剧场免费观看| 色噜噜狠狠狠综合曰曰曰| 久久人人爽人人| 久久久久久久久国产| 91视频免费在线| 国产成人福利夜色影视| 成人在线免费观看视视频| 国产精品一区二区3区| 亚洲精品电影久久久| 亚洲精品动漫久久久久| 国产一区二区在线播放| 欧美丰满片xxx777| 91国产在线精品| 日韩国产高清污视频在线观看| 1769国内精品视频在线播放| 精品国产鲁一鲁一区二区张丽| 国产日韩欧美成人| 亚洲精品久久久久久久久久久久| 亚洲欧美国产精品| 亚洲免费伊人电影在线观看av| 久久久国产精品x99av| 美乳少妇欧美精品| 国内外成人免费激情在线视频| 亚洲欧美另类人妖| 日韩有码在线播放| 91精品国产综合久久香蕉的用户体验| 亚洲色图色老头| 欧美在线视频观看免费网站| 91九色国产社区在线观看| 国产一区二区免费| 一区二区三区在线播放欧美| 亚洲国产精品va在线| 国产精品久久久久久久久久| 国色天香2019中文字幕在线观看| 成人激情av在线| 亚洲精品在线不卡| 一区二区在线视频播放| 精品国产91久久久久久老师| 欧美成人国产va精品日本一级| 2019中文字幕全在线观看| 国产视频亚洲视频| 国产欧美精品一区二区三区介绍| 性欧美激情精品| 久久精品视频在线| 成人夜晚看av| 最近2019年中文视频免费在线观看| 国产精品69精品一区二区三区| 亚洲风情亚aⅴ在线发布| 精品福利在线看| 成人黄色影片在线| 久久精品久久久久电影| 欧美福利视频在线| 九九九热精品免费视频观看网站| 欧美片一区二区三区| www高清在线视频日韩欧美| 国产精品高清在线观看| 欧美极品在线播放| 亚洲欧美国产高清va在线播| 日本不卡高字幕在线2019| 精品久久久久久电影| 国产精品极品美女粉嫩高清在线| 欧美成人免费一级人片100| 国产一区深夜福利| 中文字幕久久精品| 国产精品 欧美在线| 国产日韩欧美中文| 国产精品九九久久久久久久| 精品人伦一区二区三区蜜桃网站| 成人网在线观看| 亚洲字幕在线观看| 最近2019中文字幕mv免费看| 国产精品中文字幕在线观看| 欧美性xxxxx| 日韩高清欧美高清| 亚洲欧美第一页| 亚洲性猛交xxxxwww| 91精品久久久久久久久不口人| 亚洲一区二区三区乱码aⅴ蜜桃女| 亚洲美女在线观看| 大胆人体色综合| 亚洲精品电影网在线观看| 成人免费黄色网| 国产69精品久久久久9| 亚洲一区中文字幕| 综合国产在线视频| 欧美性jizz18性欧美| 国产一区二区丝袜高跟鞋图片| 国产精品国产三级国产aⅴ9色| 国产日本欧美一区二区三区| 日韩av成人在线观看| 欧美一级免费看| 日本高清+成人网在线观看| 国产精品久久久久av| 麻豆一区二区在线观看| 久久久av一区| 国产精品视频精品| 中文字幕日本精品| 国产日韩精品视频| 红桃视频成人在线观看| 国产一区二区三区在线视频| 国产极品jizzhd欧美| 国产美女精品视频免费观看| 亚洲欧美激情另类校园| 欧美精品成人91久久久久久久| 成人性生交大片免费观看嘿嘿视频| 亚洲精品美女久久久久| 色偷偷av亚洲男人的天堂| 国产成人精品国内自产拍免费看| 在线午夜精品自拍| 91香蕉嫩草影院入口| 成人综合国产精品| 国产精品69久久久久| 国产精品久久久久久久久久久久| 久久91精品国产91久久久| 日韩精品在线免费播放|