我来自C#世界,所以事件和事件处理程序是日常用品。 最近我一直在研究wxWidgets 我已经在谷歌上搜索了一个星期了,我发现大多数C ++程序员都很难理解“事件”或“回调”这个术语,或许它在C ++世界中含糊不清。
以下是事件模型的一个简单示例。
class A{
public:
A(){
child.MySuperClickEvent = this.HandleSuperClick;
}
private:
B child;
void HandleSuperClick(B child){
// do stuff
}
}
class B{
public:
/*TBA*/ MySuperClickEvent;
private:
void ClickPrivate(){
MySuperClickEvent(this);
}
}
B类有自己的指定目的,完成后会触发一个事件。 这个想法是B类不应该对它的领域有任何了解,使其更具可重用性。
我读过关于std :: function<>和函数指针。所有人似乎都在处理静态功能方面的例子,但一旦谈到“会员到会员”的事情就开始变得油腻。
总结一下,问题很简单。如何创建可以在外部分配给成员的成员函数指针?
答案 0 :(得分:0)
有许多方法可以实现这样的事情,在内存开销,支持多少回调,线程安全,使用例如weak_ptr
以查看所涉及的对象是否仍然存在等。
就像让你开始尝试一样 - 这是一个简单的单线程“观察者”实现,基本上可以满足你在问题中的要求:
#include <iostream>
#include <list>
struct Observer
{
virtual ~Observer() { }
virtual void on_event_x() { }
};
class Observable
{
public:
void add_observer(Observer& o)
{
observers_.push_back(&o);
}
void do_some_stuff()
{
std::cout << "before 1st event\n";
fire_event_x();
std::cout << "between 1st & 2nd events\n";
fire_event_x();
std::cout << "after 2nd event\n";
}
private:
std::list<Observer*> observers_;
void fire_event_x()
{
for (auto& observer : observers_)
observer->on_event_x();
}
};
struct My_Observer : Observer
{
My_Observer(int id) : id_(id) { }
void on_event_x() override
{
std::cout << "My_Observer::on_event_x() id " << id_ << '\n';
}
int id_;
};
int main()
{
My_Observer my_observer_1 { 1 };
My_Observer my_observer_2 { 2 };
Observable x;
x.add_observer(my_observer_1);
x.add_observer(my_observer_2);
x.do_some_stuff();
}
运行时输出:
before 1st event
My_Observer::on_event_x() id 1
My_Observer::on_event_x() id 2
between 1st & 2nd events
My_Observer::on_event_x() id 1
My_Observer::on_event_x() id 2
after 2nd event
如果这在功能上不合适,请说明原因。
答案 1 :(得分:0)
由于这个问题被标记为wxWidgets
,让我回答它的更窄的变体,即如何在wxWidgets中使用成员函数作为事件处理程序:
这是在Bind()方法的帮助下完成的,该方法可以直接与成员函数一起使用(将指针传递给函数本身和调用它的对象)或任何任意函子,即任何可以使用标准函数调用语法调用,例如std::function<>
对象,而该对象又可用于存储任何可调用对象。