【问题标题】:runtime error when the list.clear() was called调用 list.clear() 时出现运行时错误
【发布时间】:2013-12-16 13:32:42
【问题描述】:

我想用 C++ 在 Windows 编程中模拟 C# 事件驱动编程。

我想以这种方式完成:

  1. 使用列表容器保存函数指针
  2. 重写+=操作符,使Event类可以在里面添加函数 这样 event+=handlerFuncName
  3. 重写 () 操作符,这样我们就可以调用列表中的函数了

事件类:

template<class Sender_Type, class Args_Type>
class Event{
private:
    typedef void(*HFUN)(Sender_Type *, Args_Type);
    list<HFUN> handlers;
public:
    void operator +=(HFUN handler){
        handlers.push_back(handler);
    }

    void operator ()(Sender_Type *sender, Args_Type e){       
        for (list<HFUN>::iterator it = handlers.begin(); it != handlers.end(); it++)
            (*it)(sender, e);
    }

    ~Event(){ printf("Release..\n"); }
};

这是一个例子:

EventArgs 类和窗口类的定义:

class EventArgs{ };

class Win32Window
{
public:
    // event definition
    Event<Win32Window, EventArgs> Loaded;

    // ctor
    Win32Window(){
        // ...
        // trigger the Loaded event
        Loaded(this, EventArgs());
    }
    // ...
};

事件处理函数的定义:

void Window_Loaded(Win32Window *sender, EventArgs e){
    MessageBox(NULL, "Window_Loaded", "xx", 0);
}

主要功能:

Win32Window wnd;
//add the event handler function
wnd.Loaded += Window_Loaded;

它可以工作,但是当窗口关闭时,list.clear() 出现运行时错误! 这是一个snapshot 的异常:

【问题讨论】:

  • 看不到你的图片...
  • 什么是 HFUN?您能否显示初始化和清除此列表的代码,事件处理程序代码的问题不是必需的。请尝试将其减少到SSCCE
  • 成员函数指针显然不是答案。尝试阅读 Functors。
  • typedef void(*HFUN)(Sender_Type *, Args_Type);我还没有调用 clear() 函数。我认为它是在列表发布时自动调用的。对列表(处理程序)的所有操作都显示在这些代码中,不再有任何操作。
  • 使用std::function 肯定会让这更容易阅读......而且更安全

标签: c++ windows list stl


【解决方案1】:

我认为,这正是std::function 旨在帮助解决的问题。为初学者尝试这样的事情:

#include <functional>
#include <iostream>
#include <vector>

template <typename Sender, typename... Args>
class Event
{
    using FuncType = std::function<void(Sender&, Args...)>;
    std::vector<FuncType> vec;

public:
    Event& operator+=(FuncType f) {
        vec.push_back(f);
        return *this;
    }

    void operator()(Sender& s, Args... a) {
        for (auto& f : vec) {
            f(s, a...);
        }
    }
};


struct Window
{
    Event<Window, int, int> resized;

    void resize(int width, int height) {
        // blah blah
        resized(*this, width, height);
    }

};

int main()
{
    Window w;

    w.resized += [](Window&, int w, int h) {
        std::cout << "Window resized to " << w << " by " << h << std::endl;
    };

    w.resize(800, 600);
}

请注意,此方法不仅允许您使用常规函数作为事件处理程序,还可以使用 lambda(如演示)和函数对象。

【讨论】:

  • 非常感谢。这对我很有帮助。
猜你喜欢
  • 2015-07-21
  • 1970-01-01
  • 1970-01-01
  • 2021-08-24
  • 2016-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多