处理从较低级对象引发的事件

Handling events raised from a lower level object

本文关键字:事件 对象 较低级 处理      更新时间:2023-10-16

我正在用GTK+3.0编写一个c++程序。无论如何,我认为这个问题可能适用于任何使用事件/信号的框架。

我有一个容器类,说containerClass和一个子类,说childClasschildClass对象child包含在containerClass对象container中。

child对象是用来修改某些东西的属性的。为此,它有GtkEntryGtkButton等。当我单击"保存按钮"时,会引发一个事件。

此事件必须由container对象处理,因为container以某种方式与数据库连接。

此后,你找到了我用来做这项工作的解决方案:

// Child class
class childClass {
    void setClickHandler_External(void (*extFun)(string property), void *);
    void (*clickHandler_External)(string, void *);  
    void *clickHandler_External_Data;   
    static void buttonClicked(GtkWidget *widget, void *data);
}
void childClass::setClickHandler_External(void (*extFun)(string), void *data) {
    // Set the external event handler
    clickHandler_External = extFun;
    clickHandler_External_Data = data;
}
void childClass::buttonClicked(GtkWidget *widget, void *data) {
    childClass *m = (childClass *)data;
    // Call the external event handler
    m->clickHandler_External(property, m->clickHandler_External_Data);
}
// Container Class
class containerClass {
    childClass child;
    static void clickHandler(string property, void *data);
}
containerClass::containerClass() {
    // Set the event handler
    child.setClickHandler_External((void(*)(string))&(this->clickHandler), (void *)this);
}

void containerClass::clickHandler(string property, void *data) {
    // Event handler in the upper class
    containerClass *m = (containerClass *)data;
    //FINALLY, DO THE JOB WITH PROPERTY!!!
}

这个方法很有效。无论如何,我想知道是否有一种更聪明、更干净的方法来实现同样的目标,也许不使用指向静态函数的指针,或者通过定义某种模式来重用每次我需要相同的机制。

Thanks in advance

Gtkmm使用sig++库为您处理所有这些。没有必要自己写。

文档链接:

    号概述gh>
  • 附详细资料的附录

在本例中,我将使用

button.signal_clicked().connect(sigc::mem_fun(container, &containerClass::clickHandler));

同时确保containerClass::clickHander有适当数量的参数

我的第一个建议是使用use模板来提高你正在做的事情的类型安全性:

template< class ParamType >
void childClass::setClickHandler_External(void (*extFun)(string, ParamType *),
                                          ParamType *data)
{
    // Set the external event handler
    clickHandler_External = (void ()(string,void*))extFun;
    clickHandler_External_Data = (void*)data;
}

那么你可以简化containerClass的实现如下:

// Container Class
class containerClass {
    childClass child;
    static void clickHandler(string property, containerClass *data);
}
containerClass::containerClass() {
    // Set the event handler
    child.setClickHandler_External(&containerClass::clickHandler, this);
}
void containerClass::clickHandler(string property, containerClass *data) {
    //FINALLY, DO THE JOB WITH PROPERTY!!!
}

虽然这很好地清理了实现,从所有容器实现中删除了显式强制转换,但这并不是真正的重点。关键是要防止您将错误的指针传递给setClickHandler_External,从而在分派事件时导致后端崩溃。

我的下一步将带我们进一步从你的实现,但将需要更多的细节,你实际上在做什么。根据您的需要,我们将查看:

  • 继承:容器类应该从childClass派生吗?这将提供对可以重写的虚函数表的访问。
  • 函数:参考boost::function和boost::bind来实现函数,消除了中间的静态函数调用。
  • Lambda函数:前沿(c++ 11或更高版本),但可能很适合这种转发函数。