使用发射与调用信号,就好像它是Qt中的常规函数一样
比方说,我有这个信号:
signals: void progressNotification(int progress);
我最近才了解到Qt中的emit关键字。 到目前为止,我习惯于像普通函数那样调用它们来执行信号。 所以,而不是:
emit progressNotification(1000 * seconds);
我会写:
progressNotification(1000 * seconds);
像这样调用它们似乎是行得通的,所有连接的插槽都会执行,那么使用emit关键字会导致不同的行为,还是只是语法糖?
emit
只是句法糖。 如果你看看发射信号的函数的预处理输出,你会看到emit
刚刚消失。
信号发射function的生成代码中出现了“魔术”,您可以通过检查moc生成的C ++代码来查看它。
例如,一个没有参数的foo
信号产生这个成员函数:
void W::foo() { QMetaObject::activate(this, &staticMetaObject, 0, 0); }
代码emit foo();
被预处理为简单的foo();
在Qt/qobjectdefs.h
(源代码的源代码开放源代码)中定义了emit
,如下所示:
#ifndef QT_NO_EMIT # define emit #endif
(定义的守卫是允许你通过no_keywords
QMakeconfiguration选项使用Qt与其他具有碰撞名称的框架。)
18个月后……我在@Mat的回答下开始评论,很快就没了房间。 这样的答案。
IMO emit
既不是语法糖,也不是简单的关键字
- 它生成代码(如上面的@Mat所解释的),
- 它有助于
connect
机制认识到这确实是一个signal
,而且 - 它使您的信号成为“更大”系统的一部分,信号和响应(时隙)可以同步或asynchronous执行或排队,具体取决于信号发出的位置和方式。 这是信号/插槽系统非常有用的function。
整个信号/插槽系统是一个不同于一个简单的函数调用的习惯用法。 我相信这源于观察者模式。 signal
和slot
之间也有一个主要的区别:一个信号不必被执行,而一个时隙必须是 !
你走在街上,看到一个房子着火(一个信号)。 您拨打911( 用911响应插槽连接火警信号 )。 信号只是散发出来的 ,而这个插槽是由消防部门执行的。 可能是不准确的,但你明白了。 我们来看看OP的例子。
一些后端对象知道已经取得了多less进展。 所以它可以简单地emit progressNotification(...)
信号。 显示实际进度条的课程取决于该信号并在其上执行。 但是,视图如何连接到这个信号? 欢迎来到Qt的信号/插槽系统。 现在可以设想一个pipe理类(通常是一个sorting小部件),它由一个视图对象和一个数据计算对象(都是QObjects
)组成,可以执行connect (m_myDataEngine, &DataEngine::progressNotification, m_myViewObj, &SimpleView::displayProgress)
。
让我们不要深入经理类的devise方面,但足以说这是信号/时隙系统发光的地方。 我可以专注于为我的应用程序devise一个非常干净的架构。 并不总是,但往往是,我发现我只是发出信号,但实施插槽 。
如果可以使用/调用一个信号方法而没有发出信号,那么这就意味着你从来不需要这个函数作为一个信号 。
第二个选项意味着你总是知道函数名和函数参数是什么,并且你发送给它的那个对象被这个特定的函数所知道。 这两种情况并不总是正确的,所以槽和信号是两个主要的原因。 信号和插槽机制只是一个表,指向每个连接的function。
另外,看看这个pdf,它非常清楚地解释了信号和插槽机制的性质: http : //www.elpauer.org/stuff/a_deeper_look_at_signals_and_slots.pdf