2009-07-22 5 views
7

私はQt 4.5を学び始めており、シグナル/スロット機構が助けになることを発見しました。しかし、今私は自分自身が2つのタイプのアーキテクチャを検討していることがわかります。シグナル/スロット対ダイレクト関数呼び出し

これは私が

class IDataBlock 
{ 
    public: 
    virtual void updateBlock(std::string& someData) = 0; 
} 

class Updater 
{ 

    private: 
    void updateData(IDataBlock &someblock) 
    { 
     .... 
     someblock.updateBlock(data); 
      .... 
    } 
} 

注意を使用するものです:コードは、簡潔にするためにインライン化。

は今、私は可能性だけ

void Updater::updateData() 
{ 
    ... 
    emit updatedData(data); 
} 

信号とこれがクリーンで、インターフェースの必要性を低減し、私はそれだけで私ができるので、いいですか?コードの最初のブロックはより多くの型付けとより多くのクラスを必要としますが、関係を示しています。 2番目のコードブロックでは、すべてが「無形」になります。どちらがより望ましいのですか?それがケースバイケースの場合、ガイドラインは何ですか?

答えて

9

信号を送信するには、スイッチといくつかの追加のファンクションコールが必要です(どのように接続されているかによって異なります)が、オーバーヘッドは最小限に抑える必要があります。

シグナルの提供者は、そのクライアントが誰であるかを制御することはできず、実際にはすべてが実際にその時間までにシグナルを受け取ったとしても返されます。

これは非常に便利で完全なデカップリングを可能にしますが、実行の順序や何かを返すときに問題を引き起こす可能性があります。

あなたが何をしているのか正確に知っている場合を除き、決して一時的なデータへのポインタを渡してはいけません。必要ならば、メンバ変数のアドレスを渡す必要があります。Qtは、オブジェクトのすべてのイベントが処理されるまで、オブジェクトの破壊を遅延させる方法を提供します。

信号がイベントループを実行する必要があるかもしれません(接続が直接的でない限り)。

全体的に、イベント駆動型アプリケーションでは意味があります(実際には、イベントなしでは非常に迷惑になります)。

すでにプロジェクトでQtを使用している場合は、間違いなくそれらを使用してください。 Qtへの依存性が受け入れられない場合、ブーストにも同様のメカニズムがあります。

3

別の違いがあります。 #1はIDataBlockインターフェイスにハード結合されており、Updaterクラスは「someblock」について知る必要があります。 #2は、接続コール(または切断を含む複数の接続コール)を介して遅延結合することができ、より動的なアプローチにつながります。 #2はメッセージ(Smalltalk/ObjCと考える)であり、コールではない(C/C++と考える)のように振る舞います。メッセージは複数のディスパッチの対象となることもあり、#1でその機能を実装する必要があります。

私の好みは、コードの性能や即時の戻り値の必要性がそれを許容しない(またはQtへの依存が望ましくない)場合を除き、柔軟性のために信号/スロットを利用することです。

2

2つのフォームが類似しているように見えることがあります。機能的には、それは本当です。実際には、より大きな問題を解決しています。そのような場合、外部環境によってこれらの2つのソルーションは同等ではありません。

一般的なケースは、ソースとシンクの関係を把握することです。彼らはお互いを知っていますか?最初の例では、updateData()はシンクを渡す必要がありますが、トリガーが[Update Data] GUIボタンの場合はどうなりますか?プッシュボタンは汎用コンポーネントであり、IDataBlockについて知ってはいけません。

解決策はもちろんm_someblockメンバをUpdaterに追加することです。押しボタンは、Updaterのメンバーが更新されるようになりました。しかし、これは本当にあなたが意図したものですか?