C ++成员函数指针或事件驱动编程成员

时间:2016-06-22 02:02:06

标签: c++ event-handling wxwidgets

我来自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<>和函数指针。所有人似乎都在处理静态功能方面的例子,但一旦谈到“会员到会员”的事情就开始变得油腻。

总结一下,问题很简单。如何创建可以在外部分配给成员的成员函数指针?

2 个答案:

答案 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<>对象,而该对象又可用于存储任何可调用对象。