C++ 中的 GUI 工具包出现问题。将 lambda 传递到 std::function 的向量中
Posted
技术标签:
【中文标题】C++ 中的 GUI 工具包出现问题。将 lambda 传递到 std::function 的向量中【英文标题】:Trouble with a GUI toolkit in C++. Passing lambdas into a vector of std::function 【发布时间】:2019-11-27 17:58:49 【问题描述】:我遇到的问题有点难以描述,但我会尽力使其易于理解。
我正在创建一个类似于 C# 中的 Windows 窗体系统的 C++ GUI 工具包。整个系统是基于事件的。我的Event
类由std::function
的向量组成,它充当订阅者函数列表和一些实用方法。
template<class T>
class Event
public:
Event()
~Event()
void Raise(T context)
for(std::function<void(T&)> subscriber : Subscribers)
subscriber(context);
void Subscribe(std::function<void(T&)> subscriber)
try Subscribers.push_back(subscriber); catch (std::exception) /*...*/
private:
std::vector<std::function<void(T&)>>> Subscribers;
我的项目包含一个EventProvider
类,它为所有派生类提供了一堆事件。
class EventProvider
public:
Event<LoadEventContext> LoadEvent;
// ...
// ...
就像在 Windows 窗体中一样,我有一个 Window
类和一个 Control
类。他们都继承了EventProvider
。与 C# 中一样,定义所有功能的实际 Window 类必须继承 Window
类。
class Control : public EventProvider /*...*/
class Window : public EventProvider /*...*/
class MyWindow : public Window /*...*/
在我的 MyWindow
类中,我通过 lambda 将方法绑定到 Window 的事件。将MyWindow
类的方法绑定到MyWindow
类的事件可以正常工作。将控件的成员函数绑定到MyWindow
的事件也可以正常工作。在 Windows 窗体中,控件的所有事件方法也包含在 Window 类中。我想在我的项目中做同样的事情。所以MyWindow
类包含我的控件的实例、它自己的事件方法和我的控件的事件方法。但是当我尝试将控制事件函数绑定到控制事件时,我遇到了运行时错误。
// === MyWindow.hpp ===
#ifndef __MY_WINDOW_HPP__
#define __MY_WINDOW_HPP__
#include <Control.hpp>
#include <Window.hpp>
class MyWindow : public Window
public:
MyWindow();
~MyWindow();
private:
Control* button = nullptr;
void OnLoadEvent(LoadEventContext& context);
void button_OnLoadEvent(LoadEventContext& context);
#endif
// === MyWindow.cpp ===
#include <MyWindow.hpp>
MyWindow::MyWindow()
button = new Control();
LoadEvent.Subscribe([&](LoadEventContext& context) OnLoadEvent(context); ); // WORKS
LoadEvent.Subscribe([&](LoadEventContext& context) button->OnLoadEvent(context); ); // WORKS
button->OnLoadEvent.Subscribe([&](LoadEventContext& context) OnLoadEvent(context); ); // Runtime Error
MyWindow::~MyWindow() /*...*/
MyWindow::OnLoadEvent(LoadEventContext& context) /*...*/
MyWindow::button_OnLoadEvent(LoadEventContext& context) /*...*/
//
当MyWindow
调用控件的加载事件以将 lambda 函数添加到事件的订阅者函数向量中时,会在 stl 的 vector
类中引发读取访问冲突。
这行代码调用事件添加lambda函数:
button->OnLoadEvent.Subscribe([&](LoadEventContext& context) OnLoadEvent(context); ); // Runtime Error
Event
类中的这个导致了错误:
try Subscribers.push_back(subscriber); catch (std::exception) /*...*/
我在函数指针、仿函数、函数类和所有这些东西的编程方面还不是很先进。尽管如此,我希望我已经为您清楚地指出了我的问题,我希望任何人都可以帮助我解决这个问题。
【问题讨论】:
您的代码的哪一行导致了这种情况?使用工具栏上的堆栈框架来计算。 你可能想展示Subscribe()
和OnLoadEvent()
的实现
Subscribe()
的实现在Event
类中被指出,OnLoadEvent()
目前为空。
很抱歉,我不得不为这篇文章将整个系统的复杂性降低到 10%。
不要在问题标题中添加solved
。按答案左侧的绿色勾号,将问题标记为已解决。
【参考方案1】:
我明白了。问题是我在创建此控件之前将我的事件方法绑定到我的控件的事件。
【讨论】:
以上是关于C++ 中的 GUI 工具包出现问题。将 lambda 传递到 std::function 的向量中的主要内容,如果未能解决你的问题,请参考以下文章