0

この質問に正確なタイトルを付ける方法がわからないので、ここに説明があります:

編集が終了したときに、ユーザーの入力から構築されたカスタム オブジェクトでシグナルを発するカスタム ウィジェットがあります。

void GGActionEditor::finishEditing() {
  GGAction act;
  // Set up according to user input
  emit actionChanged(act);
}

このコードでは、シグナルに接続されているレシーバーは、そのオブジェクトのコピーを保存したり、適切な方法で処理したりすることができ、ウィジェットはそれを忘れることができます。

しかし、ウィジェットがクラス階層からさまざまなタイプのオブジェクトを構築できる場合、そのような状況をどのように処理するのでしょうか? お気に入り:

void GGActionEditor::finishEditing() {
  GGAction *pAct;
  // Create and set up according to user input, e.g.
  if (...) pAct = new GGSpecialAction;
  else pAct = new SimpleAction;
  emit actionChanged(pAct);
}

このような状況でオブジェクトのライフサイクルを処理するための最適なソリューションは何ですか? ウィジェットは、いずれかのレシーバーが Action オブジェクトを引き継いでいるかどうかを認識できません。また、複数のレシーバーが接続されている場合、別のオブジェクトがパラメーターを引き継いでいるかどうかを知ることはできません...
「最良の」ケースでは、これによりリークが発生する可能性があります。ただし、パラメータが複数回削除される可能性もあります。

更新:
私の実際の状況に関する詳細情報ですが、一般的な解決策にも興味があります:

渡されたオブジェクトはレシーバーによって保存され、アプリケーションのドメイン モデルに保持されます。モデルは後でそれを削除します。
簡単な解決策は、上記の「単純な」値によるケースのようにこのケースを処理することです。ただし、レシーバーがまったく接続されていない場合、オブジェクトはリークします。また、1 つのレシーバーのみがこれを行うという 100% の保証はありません (私の実際のアプリケーション ロジックではこれが当てはまりますが、この方法でチェックしたり強制したりすることはできません)。

考えられる解決策をいくつか思いついたので、コメントや追加に興味があります。

  1. うまくいくことを願っています:
    パラメータを引き継ぐレシーバが 1 つだけあると仮定します。これは私のアプリケーションではうまくいくかもしれませんが、満足していません
  2. 共有ポインタを使用する:
    Eugene が回答で述べたように、shared_ptr (または QSharedPointer) はこれを簡素化します。受信者と送信者は共有ポインターを使用するため、ライフサイクルは自動的に管理されます。しかし、これにより、ドメイン モデルは、そのような Action オブジェクトを保持するすべてのクラスに対して共有ポインターも使用するようになります。これらのクラスはアクションを集約する必要があるため、これは私のモデルにはうまく適合しません。共有ポインターは、オブジェクトに「属する」オブジェクトへの参照を保持するのに適切ではありません...
  3. 追い越しを示すパラメーターを追加:信号
    に abool*を追加します。これは、何らかの受信者がアクションを引き継いだかどうかを示します。値が true の場合、レシーバーはそれ以上追い越すことができないことを認識しています。また、受信者がオブジェクトを取得していない場合、送信者はオブジェクトを削除する必要があるかどうかを知っています。ただし、どちらの受信者がオブジェクトを取得するかは、先着順で非常にランダムです。そして、それはインターフェースを汚染します...
  4. 具象クラスごとに異なる信号を使用する:
    この場合、レシーバーのスロットは、どの具象サブクラスが使用されているかを認識し、オブジェクトのコピーを作成できますしかし、これにより、クラス階層を使用して非常にうまく実行できる信号/スロットが追加されます...また、すべてのサブクラスでコピークリエイターが利用可能でなければなりません。
  5. cloneメソッドをクラスに追加します:
    上記と同様ですが、シグナルは 1 つだけです。ポリモーフィックcloneは具象サブクラスのコピーを作成します。

  6. signal/ slotの代わりに特殊なインターフェイスを使用する:GGIActionReceiverクラスを作成し、 に最大 1 つのインスタンスを割り当てますGGActionEditor。このインスタンスは、Action オブジェクトを引き継ぐ唯一の適格なオブジェクトです。他のものは引き続き信号を送ることができますが、ポインターを追い越してはなりません。このようにして、送信者は、オブジェクトを削除する必要があるかどうかも認識します (受信者が設定されていません)。
4

1 に答える 1

0

ここでの 1 つのオプションは、std::shared_ptr<> またはその他の参照カウント メカニズムを介して共有所有権を使用することです。このようにして、オブジェクトは誰かがそれを必要とする限り存続します。

Qt の通常の所有権モデルは、同じオブジェクトの所有権を取得したいシグナル ユーザーの数がわからないため、うまく機能しません。

所有権を共有するロジックによっては、クローズド ループが発生し、それらを中断するために、抽象化に 1 つまたは 2 つの穴を開けなければならない場合があります。

Qt の所有権を shared_ptr と混同しないように注意してください。QObject に親を持たせてはなりません。

于 2013-01-15T21:45:11.837 に答える