0

クラスインスタンスを2つずつ処理しようとしています。doStuff メソッドを含む抽象基本クラス (ここでは IBase) があります。このメソッドは、他のすべての定義済みクラスを処理するために、拡張クラスでオーバーライドされます。

これは私が構築しているライブラリの一部です。Base オブジェクトをライブラリ ユーザーが作成できるようにしたい。各 Base クラスは、doStuff メソッドを介して別の Base オブジェクトと対話する必要があります。コンテナーは、複数の Base オブジェクトを処理するために必要です。

この問題に遭遇したのはこれが初めてではありませんが、前回どうしたか思い出せません。この種のクラスは、多くのことに使用できます。ここでは、衝突検出システムです。IBase は抽象的な HitBox を表し、Container は衝突が発生するシーンを表します。この場合、Container::process はヒット ボックス間の遷移をチェックし、Container::process を使用して最適化アルゴリズム (四分木など) を実装します。

私はこの方法でそれらのクラスを構築しました:

class IBase {
    public:
        virtual void doStuff(IBase* base) = 0;
}

class Base {
    public:
        virtual void doStuff(Base* base) {
            foobar();
        }
        virtual void doStuff(IBase* base) {
            // irrelevant
        }
}

class Container {
    public:
        void process() {
            for (std::list<IBase*>::iterator it=base_list.begin() ; it!=base_list.end() ; it++) {
                for (std::list<IBase*>::itarator jt=std::next(it) ; jt!=base_list.end() ; jt++) {
                    (*it)->doStuff(*jt);
                }
            }
        }
    private:
        std::list<Ibase*> base_list;
}

しかし、ループでは、2 つの Base オブジェクトを操作しているときに void Base::doStuff(Base*) に到達できません。私が望むものではない Base::doStuff(IBase*) しか呼び出せません。

これについて何か助けはありますか?問題は理解できますが、解決策がわかりません。これはそれを処理する良い方法ですか、それとも自分のアーキテクチャをもう一度考える必要がありますか? これをどうしますか?このような問題には設計パターンが存在するに違いないと思いますが、適合するものは見つかりませんでした。

ありがとう

4

2 に答える 2

1

*itおよびから参照解除されたオブジェクトは、Base オブジェクトではなく、オブジェクト*jtとして参照されます。IBaseこれは、 のメソッドのみをIBase呼び出すことができることを意味します。

あなたの仮想メソッド:

virtual void doStuff(Base* base) { ... }

何もオーバーライドしていません。ベースから下方向にのみアクセスできる新しい仮想メソッドを作成しています。ポインターdoStuffから呼び出すと、次のように呼び出されます。IBase

virtual void doStuff(IBase* base) { ... }

で定義されている署名と一致しIBaseます。

関数を実行する場合は、オーバーライドに基づいているときにfoobar何らかのチェックを行い、安全であることを確認したらキャストしてから、必要に応じて操作する必要があります。basedoStuffBase*

virtual void doStuff(IBase* base) {
  // not irrelevant
  if (base->isBase()) 
  {
    foobar();
  }
}

最後に、以前に提案したように、doStuff公開します。

于 2013-06-10T20:14:33.727 に答える