それがQtの通常の関数であるかのように、発行を使用して信号を呼び出す


97

この信号があるとしましょう:

signals:
    void progressNotification(int progress);

最近、Qtの出力キーワードについて学びました。これまでは、通常の関数のように呼び出すだけで信号を実行していました。だから代わりに:

emit progressNotification(1000 * seconds);

私は書きます:

progressNotification(1000 * seconds);

そのようにそれらを呼び出すことは機能しているようで、接続されたすべてのスロットが実行されるので、emitキーワードを使用すると別の動作が発生しますか、それとも単なる構文上の砂糖ですか?


17
+1知らないことemitは必要ない。しかし、奇妙なことにemit、シグナルスロットシステムはQtについて最初に学んだことの1つであるため、シグナルを直接呼び出してからずっと後について学びました。
Christian Rau

回答:


88

emit単なる構文上の砂糖です。シグナルを発信する関数の前処理された出力を見ると、表示されていないことがわかりますemit

「マジック」は、シグナル発信機能用に生成されたコードで発生します。これは、mocによって生成されたC ++コードを調べることで確認できます。

たとえば、fooパラメーターのない信号は次のメンバー関数を生成します。

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

そして、コードemit foo();は簡単に前処理されますfoo();

emitQt/qobjectdefs.hとにかく(ソースのオープンソースフレーバーで)次のように定義されています:

#ifndef QT_NO_EMIT
# define emit
#endif

(定義ガードは、no_keywordsQMake構成オプションを介して衝突する名前を持つ他のフレームワークでQtを使用できるようにすることです。)


14
emit実際に何もしなかった以上の実装(または計画された実装)があったかどうかを知っていますか?この場合の「構文糖」を持つことは、初心者(または少なくとも私がQtの初心者だったときは私)を混乱させるだけであることがわかります- emit疑似キーワードが何も実行しない場合、疑似キーワードで何かが起こっているようですall-すべての魔法は、moc作成する通常の古い関数で発生します(mocQtシグナルとスロットの魔法です)。emit重要なように見えるだけの無駄な装飾です。
Michael Burr

12
放出は「単なる装飾」ではありませんemit呼び出しを読んでいる人に魔法が起きようとしていることを伝えます(つまり、これにより、このクラスが聞いたことのないオブジェクトのコードがトリガーされ、これらの呼び出しは同期または非同期になる可能性があります)。これは、キーワードを省略した場合、基本的に完全に失われます。これを使って。自動ドキュメント化です。「初心者」はドキュメントとチュートリアルを読む必要emitがあり、常にそこにあります(とにかく公式ドキュメントにあります)。関数を呼び出すことができることは、「光を見た」後に発生するはずです。その時点では、初心者ではありません。
マット

19
うーん、emit「キーワード」がどれほど価値があるかについて、あなたに同意するかどうかはわかりません。関数呼び出しがシグナルであることを明確にする必要がある場合は、命名規則を使用した方がよいと思います。
Michael Burr

2
まあ、私はそれと根本的に反対します:)命名規則を強制することはあなたがあなたのプロジェクト/職場で自分でできることです、Qtはそれを妨げません。Qtは「キーワード」を使用することを強制せず、コードの他の部分と衝突した場合にそれをオフにすることもできます。私の意見では、キーワードアプローチの方が優れています。コンパイラは命名ポリシーを適用するのに役立ちませんが、スペルミスをキャッチしemitます。
マット

15
明確にするために-私は命名規則を使用することを主張していませんでした- 仮にemitキーワードキーワードコメントの理由が信号が呼び出されていることを明確にするためなら、命名規則は同じことをすることができました謎と同様の利点。命名規則はQtによって強制することはできませんが(実際にmocは強制できますが、私はそれを主張していません)、Qtはemitどちらの使用も強制できません。またemit、名前の衝突がある場合は「無効にする」ことができますが、それを使用しているソースファイルがたくさんある場合は(あまりにも、起動するために)あまり役に立ちません。
Michael Burr

2

18か月後... @Matの回答の下にあるコメントから始めましたが、すぐに部屋が足りなくなりました。したがって答え。

IMO emitは、構文上の砂糖でもありませんし、単純なキーワードでもありません。

  1. (上記の@Matで説明されているように)コードを生成します。
  2. それは助けconnectメカニズムが実際にそれがあることを認識signalし、
  3. これは、信号を「より大きな」システムの一部にし、信号と応答(スロット)を同期または非同期で実行したり、信号がどこでどのように送信されたかに応じてキューに入れたりすることができます。これは、信号/スロットシステムの非常に便利な機能です。

信号/スロットシステム全体は、単純な関数呼び出しとは異なるイディオムです。それはオブザーバーのパターンに由来すると思います。a signalとaの間にも大きな違いがありますslot。信号実装する必要はありませんが、スロット実装する必要があります

あなたは通りを歩いていて、火がついている家(信号機)を見ています。911をダイヤルします(火災信号を911応答スロットに接続します)。信号は発信されただけでしたが、スロット消防署によって実装されました。不正確かもしれませんが、あなたはアイデアを得ます。OPの例を見てみましょう。

一部のバックエンドオブジェクトは、どれだけの進捗があったかを認識しています。したがって、単にemit progressNotification(...)信号を送ることができます。実際のプログレスバーを表示するクラスは、この信号を取得して実行するかどうかに依存します。しかし、ビューはこの信号にどのように接続しますか?Qtのシグナル/スロットシステムへようこそ。これで、ビューオブジェクトとデータ計算オブジェクト(両方QObjects)で構成されるマネージャークラス(通常は一種のウィジェット)が実行できると考えることができますconnect (m_myDataEngine, &DataEngine::progressNotification, m_myViewObj, &SimpleView::displayProgress)

マネージャークラスの設計の側面については触れませんが、ここで信号/スロットシステムが優れていると言えます。私は、アプリケーションの非常にクリーンなアーキテクチャの設計に集中できます。常にではありませんが、多くの場合、シグナル発信するだけでスロットを実装します

シグナルメソッドを使用せずに呼び出すことができる場合、シグナルメソッドを発行することできません。その場合、そもそもシグナルとしてその機能が必要なかったということです


6
いいえ、emit確かに空のマクロであり、純粋にオプションです。それほどのキーワードがあるsignalslotどのMOCによって処理されています。signalは、関数の実装を提供するためにslot使用され、メタオブジェクトエントリを作成するために使用されるため、SLOT(MySlot())マクロまたはQMLで検出されます。emit構文のシュガーです。あなたが書いてもemit i++;(おそらくあなたの同僚も)、それでもに接続できない場合、何も文句を言うことはありませんi++
derM 2018

-5

2番目のオプションは、関数名と関数パラメーターが何であるかを常に知っており、送信先のオブジェクトがその特定の関数によって認識されていることを意味します。これらの2つのケースは常に当てはまるとは限らないため、スロットと信号が作成された2つの主な理由はそれです。「内部」シグナルとスロットのメカニズムは、接続されているすべての機能へのポインタを備えた単なるテーブルです。

また、信号とスロットのメカニズムの性質を非常に明確に説明しているこのpdfを見てくださいhttp : //www.elpauer.org/stuff/a_deeper_look_at_signals_and_slots.pdf


どちらの方法でも、信号名とそのパラメータを知る必要があります。信号を発信しているのですが、知らないものをどのようにして発信できますか?どちらも同じセマンティクスを持ち、同じです。
マット

1
多分あなたは直接のスロットコールでシグナルコールを台無しにしていますか?しかし、私は最初は質問のタイトルについても疑問に思ったことを認めなければなりemitません。ただし、この場合でも、質問の本文を読んだだけで問題は解決されたはずなので、-1を返します。
Christian Rau
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.