我想知道这是否是一种可接受的写回调的方法:
存储回调:
struct EventHolder {
std::function<void()> Callback;
EventTypes::EventType Type;
};
std::vector<Events::EventHolder> EventCallbacks;
方法定义:
void On(EventType OnEventType,std::function<void()>&& Callback)
{
Events::EventHolder NewEvent;
NewEvent.Callback=std::move(Callback);
NewEvent.Type=OnEventType;
EventCallbacks.push_back(std::move(NewEvent));
}
绑定事件:
Button->On(EventType::Click,[]{
// ... callback body
});
我最大的问题是关于通过值传递回调。这是一种有效的方法吗?
答案 0 :(得分:12)
这是存储事件处理程序的完美有效方法。
但是,我想指出一些关于添加回调函数签名的细节。你担心通过值和引用传递它。在您的示例中,您目前拥有:
void On(EventType OnEventType,std::function<void()>&& Callback)
这很好,只要你只将它绑定到右值。但是,除非您有特殊原因要禁止它,否则我建议您始终使用一个方法接受按值或左值引用的参数,并在必要时添加右值参考版本作为补充。
没有采用左值引用的方法意味着您的代码目前无法编译,因为:
std::function<void()> func([](){/*something clever*/});
// Do something necessary with func, perhaps logging or debug prints.
Button->On(EventType::Click, func);
为简单起见,无论何时选择如何传递值,您都可以简单地遵循以下指南:
答案 1 :(得分:1)
是。函数是原始函数指针或轻量级类,它们的复制构造函数没有副作用,因此它们的副本必须充当原始对象,因此这种方法完全没问题。但是为什么你按值传递对象然后将其移动到原始容器,你可以传递引用,然后将它复制到你的容器,并有一个接受r值引用的重载函数(不应该那么重要)。
答案 2 :(得分:0)
我有几乎相同的问题。 我想知道有多少台监视器以及它们在哪里。
至少我放弃并写了一个简短的结构。 不好,但是我只想要信息。
即使我尝试过Lambda,也没有机会定义Lambda ... 不是固定的地址,其次不能构造为回呼...
#include <WinUser.h>
#include <vector>
using namespace std;
struct _sMonitors{
struct DispInfo {
HMONITOR hMon;
// HDC dcMon; // Everytime NULL (What ever!)
RECT pRcMon;
};
list< DispInfo> List;
_sMonitors() {
EnumDisplayMonitors(0, 0, Func, (LPARAM)this);
}
BOOL static CALLBACK Func(HMONITOR hMon, HDC dcMon, LPRECT pRcMon, LPARAM lParam){
auto& Struct = *((_sMonitors*)lParam);
Struct.List.push_back({ hMon,*pRcMon });
return 1;
}
};
_sMonitors Monitors;
正如我用我的语言所说! Mann ging mir das auf den Sack ...