对于一个小的GUI,我首先想使用函数指针;在阅读了很多东西之后,我发现Lambda回调函数可能是更好的解决方案(?)。
我总是收到读取访问冲突,并猜测我缺少一些重要知识。 如果我在 lambda 调用中使用复制或引用构造函数没有区别 - 我仍然得到异常。
#include <iostream>
#include <functional>
using namespace std;
//=======================================================
class Button {
private:
function<void()> const &callback;
public:
Button(function<void()> const &c) : callback(c) {
cout << "created Button" << endl;
callback(); // THIS CALL WORKS FINE
}
void update() {
// if(clicked)...
callback(); // HERE I GET THE READ ACCESS VIOLATION
}
};
//=======================================================
class VideoPreview {
private:
Button *btn;
public:
VideoPreview() {
cout << "created VideoPreview" << endl;
btn = new Button([=]() {
//cout << "you clicked the button" << endl;
buttonClicked();
});
}
void update() { // "check the gui"
btn->update();
}
void buttonClicked() {
cout << "you clicked the button" << endl;
}
};
//=======================================================
void main() {
VideoPreview foo;
foo.update();
}
这里的问题是function<void()> const &callback;
不会std::function
延长从
btn = new Button([=]() {
//cout << "you clicked the button" << endl;
buttonClicked();
});
lambda 不是std::function
因此当您执行上述操作时,会生成临时std::function
。 然后,您可以使用callback
绑定到该临时变量const&
但成员变量不会延长它们绑定到的临时变量的生存期。 只有函数本地const&
才能获得该行为。 这意味着当你退出VideoPreview
的构造函数时,你留下了一个按钮,该按钮具有对已销毁对象的函数引用。
要解决此问题,只需按值存储callback
,例如
class Button {
private:
function<void()> callback;
public:
Button(function<void()> c) : callback(std::move(c)) {
cout << "created Button" << endl;
callback(); // THIS CALL WORKS FINE
}
void update() {
// if(clicked)...
callback(); // works now.
}
};