0

次のように、パラメーターの特殊化に基づいてオーバーロードされる関数を作成しようとしています。

class DrawableObject...;
class Mobile : public DrawableObject...;

class Game
{
    AddObject(DrawableObject * object)
    {
        // do something with object
    }
    AddObject(Mobile * object)
    {
        AddObject(dynamic_cast<DrawableObject *>(object));
        DoSomethingSpecificForSpecializedClass();
    }
};

...しかし、私のMSコンパイラは私にこのエラーを与えています:

エラー C2681: 'Mobile *': dynamic_cast の式の型が無効です

どちらのクラスにも仮想関数があります。この状況でのアップキャストのキャストは間違っていますか? 私は C スタイルのキャストを試してみましたが、すべてが意図したとおりに機能します。また、この設計に潜在的な落とし穴はありますか?

4

5 に答える 5

4

明示的なアップキャストには、 を使用しますstatic_cast

あなたのデザインはうまくいくはずです。から派生したクラスへのポインタなど、とのAddObject()両方に暗黙的に変換できるオブジェクトを渡そうとすると、への呼び出しがあいまいになることに注意してください。Mobile*DrawableObject*Mobile

于 2010-01-07T21:46:02.490 に答える
1

ニールが述べたように、キャストは単に間違っています。 ベースから派生へのダウンキャストdynamic_cast<>用であり、その逆ではありません。より良いアプローチは、次のような一般的なコードを除外することです。

class Game {
protected:
    void commonAddObject(DrawableObject *obj) {
        // do common stuff here
    }
public:
    void addObject(DrawableObject *obj) {
        commonAddObject(obj);
        // do DrawableObject specific stuff here
    }
    void addObject(MobileObject *obj) {
        commonAddObject(obj);
        // do MobileObject specific stuff here
    }
};

または、タイプによるオーバーロードに依存しないDrawableObjectとの個別のメソッドを作成します。MobileObjectできれば、キャストを完全に避けたいと思います。

于 2010-01-07T22:09:52.337 に答える
0

アップキャストは常に無料で安全です。つまり、保護された dynamic_cast を使用する必要はありません。これを行うには static_cast が適切な方法ですが、C スタイルのキャストも同様に機能します。実際には、2 番目の AddObject 関数を省略できるはずです。なぜなら、Mobile オブジェクトへのポインターを DrawableObject 関数に渡すと、キャストを必要とせずに適切な関数が呼び出されるからです。オーバーロードされた関数に特殊な機能を配置することを計画していない限り、私はそれを書きません。

于 2010-01-07T21:57:35.827 に答える
0

キャストが間違っており、完全に不必要です - Mobile はすでに DrawableObject です。

于 2010-01-07T21:47:53.850 に答える
0

...または AddObject(Mobile * object) オーバーロードを完全に削除します。その関数がなければ、その基本クラスに「暗黙的にキャスト」され、AddObject(DrawableObject*) 関数が呼び出されます。階層内の型ごとにオーバーロードとキャストを手動で追加する必要はありません。

編集コードが追加されました。デザインに関するいくつかの提案を明確にしたいと思います。

「ゲーム」クラスがすべてのオブジェクトを一様に扱うか、そうでないかのどちらかです。そうでない場合は、一般に公開されている一般的な「AddObject」オーバーロードを提供しても意味がありません。すでに個々のオブジェクトに緊密に結合しているため、それと疎結合設計のシャレードを削除することもできます..これをプライベート ヘルパー関数 AddObjectInternal として使用することもできます。これはオーバーロードではないため、呼び出しを明確にするためのキャストは必要ありません。

すべてのオブジェクトを一様に扱う場合、または扱うことを希望する場合は、現在 AddObject オーバーロードに入れているロジックをオブジェクト クラスの仮想関数に入れることを検討してください。次に、追加されたオブジェクトの仮想関数を呼び出す AddObject メソッドが 1 つだけになります。

于 2010-01-07T21:50:19.593 に答える