将发出函数与调用信号相比,就好像它是 Qt 中的一个常规函数一样

假设我有这个信号:

signals:
void progressNotification(int progress);

我只是最近才了解 Qt 中的稿件关键字。到目前为止,我一直通过像调用常规函数一样调用它们来执行信号。所以不是:

emit progressNotification(1000 * seconds);

我会写:

progressNotification(1000 * seconds);

Calling them like that seemed to work, and all the connected slots would execute, so does using the emit keyword cause a different behaviour, or is it just syntactic sugar?

82931 次浏览

第二个选项意味着您始终知道函数名和函数参数是什么,并且您将其发送到的对象是该特定函数所知道的。这两种情况并不总是正确的,所以这就是为什么有插槽和信号的两个主要原因。“引擎盖下”的信号和插槽机制只是一个表与指针的每个功能是连接。

另外,看看这个 pdf,它非常清楚地解释了信号和插槽机制的性质: Http://www.elpauer.org/stuff/a_deeper_look_at_signals_and_slots.pdf

emit is just syntactic sugar. If you look at the pre-processed output of function that emits a signal, you'll see emit is just gone.

“魔术”发生在为信号发射函数生成的代码中,您可以通过检查 moc 生成的 C + + 代码来查看这些代码。

例如,没有参数的 foo信号生成这个成员函数:

void W::foo()
{
QMetaObject::activate(this, &staticMetaObject, 0, 0);
}

代码 emit foo();被预处理成简单的 foo();

emit is defined in Qt/qobjectdefs.h (in the open-source flavor of the source anyway), like this:

#ifndef QT_NO_EMIT
# define emit
#endif

(定义约束允许您通过 no_keywords QMake 配置选项将 Qt 与其他名称冲突的框架一起使用。)

18个月后... ... 我开始在@Mat 的回答下评论,很快就没有空间了。这就是答案。

IMO emit既不是语法上的糖,也不是一个简单的关键字

  1. 它生成代码(如上面@Mat 所解释的) ,
  2. 它帮助 connect机制认识到它确实是一个 signal,并且
  3. 它使您的信号成为一个“更大”系统的一部分,在这个系统中,信号和响应(插槽)可以同步或异步执行,或者排队,这取决于信号发出的位置和方式。这是信号/插槽系统的一个非常有用的特性。

整个信号/插槽系统不同于简单的函数调用。我相信是观察者模式的原因。在 signalslot之间也有一个主要的区别: 一个信号 does not have将被实现,而一个插槽 must be

你走在街上,看到一所房子着火了(一个信号)。你拨打911(将火警信号与911响应插槽连接起来)。信号是 只发射,而槽 实施由消防部门。也许不够精确,但你明白我的意思。让我们看看 OP 的例子。

一些后端对象知道已经取得了多少进展。所以它可以简单地 emit progressNotification(...)信号。这取决于显示实际进度条的类,它拾取这个信号并在其上执行。但是视图是如何连接到这个信号的呢?欢迎使用 Qt 的信号/插槽系统。现在可以设想一个管理器类(通常是排序的小部件) ,它由一个视图对象和一个数据计算对象(都是 QObjects)组成,可以执行 connect (m_myDataEngine, &DataEngine::progressNotification, m_myViewObj, &SimpleView::displayProgress)

让我们不要深入到 Manager 类的设计方面,但是只要说这是信号/槽系统的亮点就够了。我可以专注于为我的应用程序设计一个非常干净的体系结构。不总是,但经常的时候,我发现我 只是发射信号,但实现插槽

如果可以使用/调用信号方法 却从未释放出来,那么它必然意味着 你根本不需要那个信号首先。