提问人:sashoalm 提问时间:4/15/2012 最后编辑:sashoalm 更新时间:1/8/2017 访问量:88778
使用emit与调用信号,就好像它是Qt中的常规函数一样
Using emit vs calling a signal as if it's a regular function in Qt
问:
假设我有这个信号:
signals:
void progressNotification(int progress);
我最近才知道Qt中的emit关键字。到目前为止,我曾经通过像常规函数一样调用信号来执行信号。因此,而不是:
emit progressNotification(1000 * seconds);
我会写:
progressNotification(1000 * seconds);
这样调用它们似乎有效,并且所有连接的插槽都会执行,那么使用 emit 关键字是否会导致不同的行为,或者它只是语法糖?
答:
第二个选项意味着您始终知道函数名称和函数参数是什么,并且该特定函数知道您发送到的对象。这两种情况并不总是正确的,所以这是产生插槽和信号的两个主要原因。“在引擎盖下”,信号和插槽机制只是一个表格,其中包含指向连接的每个功能的指针。
另外,请看这个pdf,它非常清楚地解释了信号和插槽机制的性质:http://www.elpauer.org/stuff/a_deeper_look_at_signals_and_slots.pdf
评论
emit
emit
只是句法糖。如果你看一下发出信号的函数的预处理输出,你会发现它就这样消失了。emit
“魔术”发生在信号发射函数生成的代码中,您可以通过检查 moc 生成的 C++ 代码来查看。
例如,没有参数的信号会生成以下成员函数:foo
void W::foo()
{
QMetaObject::activate(this, &staticMetaObject, 0, 0);
}
并且代码经过预处理,以简化emit foo();
foo();
emit
定义在(无论如何在源代码的开源风格中),如下所示:Qt/qobjectdefs.h
#ifndef QT_NO_EMIT
# define emit
#endif
(定义保护是允许您通过QMake配置选项将Qt与其他具有冲突名称的框架一起使用。no_keywords
评论
emit
emit
moc
moc
emit
emit
emit
emit
emit
emit
moc
emit
emit
18个月后......我从@Mat的回答下发表评论开始,很快就用完了。因此,答案就是这样。
IMO 既不是句法糖,也不是一个简单的关键字,从某种意义上说emit
- 它生成代码(如上@Mat所述),
- 它有助于机制认识到它确实是一个 ,并且
connect
signal
- 它使您的信号成为“更大”系统的一部分,其中信号和响应(时隙)可以同步或异步执行,也可以排队执行,具体取决于信号的发射位置和方式。这是信号/时隙系统的一个非常有用的功能。
整个信号/时隙系统与简单的函数调用不同。我相信它源于观察者模式。a 和 a 之间还有一个主要区别:信号不必实现,而插槽必须实现!signal
slot
你走在街上,看到一所房子着火了(一个信号)。您拨打 911(将火警信号与 911 响应插槽连接)。信号仅发出,而插槽由消防部门实施。可能不精确,但你明白了。让我们看一下 OP 的例子。
一些后端对象知道已经取得了多少进展。所以它可以简单地发出信号。由显示实际进度条的类来获取此信号并对其执行。但是视图如何连接到这个信号呢?欢迎来到Qt的信号/时隙系统。现在可以设想一个管理器类(通常是某种小部件),它由视图对象和数据计算对象(两者都是)组成,可以执行。emit progressNotification(...)
QObjects
connect (m_myDataEngine, &DataEngine::progressNotification, m_myViewObj, &SimpleView::displayProgress)
我们暂且不讨论管理器类的设计方面,但只要说这是信号/插槽系统的亮点就足够了。我可以专注于为我的应用程序设计一个非常干净的架构。并非总是如此,但很多时候,我发现我只是发出信号,但实现了插槽。
如果可以使用/调用信号方法而不发出信号,那么它必然意味着您从一开始就不需要该函数作为信号。
评论
emit
signal
slot
signal
slot
SLOT(MySlot())
emit
emit i++;
i++
emit
评论
emit
emit