使用emit vs调用一个信号就好像它是Qt中的常规函数​​一样

sas*_*alm 92 c++ qt

假设我有这个信号:

signals:
    void progressNotification(int progress);
Run Code Online (Sandbox Code Playgroud)

我最近才了解到Qt中的emit关键字.到目前为止,我曾经通过像普通函数一样调用信号来执行信号.所以代替:

emit progressNotification(1000 * seconds);
Run Code Online (Sandbox Code Playgroud)

我会写:

progressNotification(1000 * seconds);
Run Code Online (Sandbox Code Playgroud)

像这样调用它们似乎工作,所有连接的插槽都会执行,使用emit关键字会导致不同的行为,还是只是语法糖?

Mat*_*Mat 82

emit只是语法糖.如果你看一下发出信号的函数的预处理输出,你会发现emit它已经消失了.

"魔术"发生在生成的信号发射函数代码中,您可以通过检查moc生成的C++代码来查看.

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

void W::foo()
{
    QMetaObject::activate(this, &staticMetaObject, 0, 0);
}
Run Code Online (Sandbox Code Playgroud)

并且代码emit foo();被预处理为简单foo();

emit定义在Qt/qobjectdefs.h(无论如何在源代码的开源风格中),如下所示:

#ifndef QT_NO_EMIT
# define emit
#endif
Run Code Online (Sandbox Code Playgroud)

(定义保护是允许您通过no_keywordsQMake配置选项将Qt与其他具有冲突名称的框架一起使用.)

  • 嗯,我不确定我同意你对'emit`'关键字'有多大价值.我想如果需要明确函数调用是一个信号,我宁愿使用命名约定. (16认同)
  • 要明确一点 - 我并不主张使用命名约定 - 只是*如果*发出`发送'psuedo-keyword-comment的原因是要明确调用信号,那么命名约定就可以了同样,没有神秘感和类似的好处.Qt无法强制命名约定(实际上,`moc`可以强制执行它 - 但我也不提倡它),但Qt也不能强制使用`emit`.虽然如果有名称冲突你可以'关闭'`emit`,如果你有一堆使用它的源文件(不必要地,开机),那就没有多大帮助. (13认同)
  • 你知道是否有一个'emit`的实现(或计划实现)实际上做的比什么都没有?我发现在这种情况下使用'syntactic sugar'只会让初学者感到困惑(或者至少我是新手Qt用户时) - 看来,`emit`伪关键字会发生一些神奇或重要的事情.什么都不做 - 所有的魔法都发生在`moc`创建的常规旧函数中(`moc`是Qt信号和插槽的神奇之处).`emit`是不必要的装饰,除了看起来很重要之外什么都不做. (12认同)
  • Emit是_not_"只是装饰".`emit`告诉读取调用的人魔法将要发生(即这将触发此类可能从未听说过的对象中的代码,并且这些调用可能是同步的或异步的),如果省略则基本完全丢失关键字.用它.它是自动记录的."新手"应该阅读文档和教程,并且`emit`总是在那里(无论如何在官方文档中).发现你可以调用这个函数应该在你"看到光"之后发生 - 那时你不再是新手了. (10认同)
  • 好吧,我完全不同意这一点:) 强制命名约定是你可以在你的项目/工作场所自己做的事情,Qt 不会阻止这一点。Qt 不会强迫您使用“关键字”,甚至允许您在它与代码的其他部分发生冲突时将其关闭。在我看来,关键字方法更好 - 编译器无法帮助您强制执行命名策略,但它会捕获拼写错误的 `emit`。 (2认同)