C++ 中的 GUI 工具包出现问题。将 lambda 传递给 std::function 的向量
Trouble with a GUI toolkit in C++. Passing lambdas into a vector of std::function
我遇到的问题有点难以描述,但我会尽力使其易于理解。
我正在创建一个类似于 Windows C# 表单系统的 C++ GUI 工具包。整个系统是基于事件的。我的 Event
class 包含一个 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,它为所有派生的 classes 提供一堆事件。
class EventProvider
{
public:
Event<LoadEventContext> LoadEvent;
// ...
// ...
}
也像 Windows 表格一样,我有一个 Window
class 和一个 Control
class。他们都继承了EventProvider
。就像在 C# 中一样,定义所有功能的实际 Window class 必须继承 Window
class.
class Control : public EventProvider { /*...*/ }
class Window : public EventProvider { /*...*/ }
class MyWindow : public Window { /*...*/ }
在我的 MyWindow
class 中,我通过 lambda 将方法绑定到 Window 的事件。将 MyWindow
class 的方法绑定到 MyWindow
class 的事件就可以了。将控件的成员函数绑定到 MyWindow
的事件也没有问题。在Windows窗体中,控件的所有事件方法也包含在Windowclass中。我想在我的项目中做同样的事情。所以 MyWindow
class 包含我的控件的实例,它自己的事件方法和我的控件的事件方法。但是,当我尝试将控件事件函数绑定到控件事件时,出现运行时错误。
// === 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
class.
这行代码调用了添加 lambda 函数的事件:
button->OnLoadEvent.Subscribe([&](LoadEventContext& context) { OnLoadEvent(context); }); // Runtime Error
而 Event
class 中的这个导致了错误:
try { Subscribers.push_back(subscriber); } catch (std::exception) { /*...*/ }
我在使用函数指针、仿函数、类函数和所有这些东西进行编程方面仍然不是很先进。尽管如此,我希望我已经为您清楚地指出了我的问题,我希望任何人都可以帮助我解决这个问题。
我明白了。问题是我在完全创建此控件之前将我的事件方法绑定到我的控件的事件。
我遇到的问题有点难以描述,但我会尽力使其易于理解。
我正在创建一个类似于 Windows C# 表单系统的 C++ GUI 工具包。整个系统是基于事件的。我的 Event
class 包含一个 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,它为所有派生的 classes 提供一堆事件。
class EventProvider
{
public:
Event<LoadEventContext> LoadEvent;
// ...
// ...
}
也像 Windows 表格一样,我有一个 Window
class 和一个 Control
class。他们都继承了EventProvider
。就像在 C# 中一样,定义所有功能的实际 Window class 必须继承 Window
class.
class Control : public EventProvider { /*...*/ }
class Window : public EventProvider { /*...*/ }
class MyWindow : public Window { /*...*/ }
在我的 MyWindow
class 中,我通过 lambda 将方法绑定到 Window 的事件。将 MyWindow
class 的方法绑定到 MyWindow
class 的事件就可以了。将控件的成员函数绑定到 MyWindow
的事件也没有问题。在Windows窗体中,控件的所有事件方法也包含在Windowclass中。我想在我的项目中做同样的事情。所以 MyWindow
class 包含我的控件的实例,它自己的事件方法和我的控件的事件方法。但是,当我尝试将控件事件函数绑定到控件事件时,出现运行时错误。
// === 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
class.
这行代码调用了添加 lambda 函数的事件:
button->OnLoadEvent.Subscribe([&](LoadEventContext& context) { OnLoadEvent(context); }); // Runtime Error
而 Event
class 中的这个导致了错误:
try { Subscribers.push_back(subscriber); } catch (std::exception) { /*...*/ }
我在使用函数指针、仿函数、类函数和所有这些东西进行编程方面仍然不是很先进。尽管如此,我希望我已经为您清楚地指出了我的问题,我希望任何人都可以帮助我解决这个问题。
我明白了。问题是我在完全创建此控件之前将我的事件方法绑定到我的控件的事件。