1

だから私は個人的なプロジェクトに取り組んでいます(c ++でより良くしようとしています)、そして私はこれを機能させようとしています:

純粋仮想関数interactWith(A * target);を持つABCクラスAがあります。

次に、クラスBとクラスCの2つの派生クラスがあります。

ただし、クラスBは、別のクラスBとは異なる方法でクラスCと対話する必要があります。

ABCでif/elseと仮想getType()を使用してこれを行う1つの方法を見つけましたが、もっとエレガントな方法があるのか​​、それとも非常に愚かなことをしているのか、そして何かをしているのか興味がありました。愚かな(これは非常に可能です)、どこでより良い解決策(つまり、より適切なデザインパターン)を探し始めますか?

注意:私はブーストを使用していません。今はブーストを使用せず、実際にプログラミングが得意なときに学習を開始します。

あなたが提供できるどんな助けでも歓迎されるでしょう。どうぞよろしくお願いします

注意すべき点:クラスBとCは、A *を介してのみ表示されます(表示されるはずです)。

4

4 に答える 4

2

実装しようとしているのは、ダブルディスパッチと呼ばれます。2つのオブジェクトに関して仮想として動作する関数です。

これを実装する方法はいくつかありますが、最も一般的な方法の1つは、ビジターパターンの使用です。

Scott Meyersには、ダブルディスパッチの実装に関する優れた章があります(彼の「より効果的なC ++」の本の項目#31)。彼はビジターパターンの議論から始め、次にRTTIを使用した非常に優れた実装に進みます。

于 2012-06-07T00:32:20.967 に答える
2

タイプスイッチングを使用することはほとんどありません。動的キャストの方が少し優れていますが、可能であれば避ける必要があります。

より良い代替策は、「ダブルディスパッチ」または「マルチメソッドのシミュレーション」と呼ばれることが多い仮想ディスパッチメカニズムを再び使用できるように、状況を好転させることです。次のようになります。

struct B;

struct A { 
  virtual void interactWith(A* target); 
  virtual void interactWithB(B* target);
};

struct B : A {
  virtual void interactWith(A* target) {
    target->interactWithB(this);
  }
  virtual void interactWithB(B* lhs) {
    // B vs. B stuff goes here, but with lhs and this in place of this and target
  }
};

struct C : A {
  virtual void interactWith(A* target) {
    // C vs. anything stuff goes here
  }
  virtual void interactWithB(B* lhs) {
    // B vs. C stuff goes here, again backward
  }
};
于 2012-06-07T00:32:56.460 に答える
0

dynamic_castを使用する

C* cTarget = dynamic_cast<C*>(target);
if(cTarget == NULL)
{
    //cTarget is not a C
}
else if(cTarget)
{
    //cTarget is a C
}

dynamic_castは、キャストが有効であることを確認するためにいくつかの凝ったことを行い(何をするのかわかりません)、そうでない場合はNULLを返します。

于 2012-06-07T00:28:07.130 に答える
0

理想的には、BとCの間で対話するときに異なる必要がある動作をカプセル化し、それを呼び出す別の仮想メソッドに配置します。targetその後、必要に応じて、BとCでそのメソッドの異なる実装が行われます。

上記が混乱しすぎて散在している場合は、オブジェクトとして間違った抽象化を選択したことを示しています。A / B / Cクラス階層を破棄し、プログラムを別の階層に分割する方がよい場合がありますが、何をしようとしているのかをより具体的に説明することは不可能です。時期尚早の抽象化(時期尚早の最適化とともに)は、経験の浅いプログラマーがしばしば犯す重要な間違いの1つです。

于 2012-06-07T00:35:28.347 に答える