5
    template <class T> void checkObject(T genericObject)
    {
      MyClassA* a = dynamic_cast<MyClassA*>(genericObject);
      if (a != NULL)
      {
        //we know it is of type MyClassA
      }
      MyClassB* b = dynamic_cast<MyClassB*>(genericObject);
      if (b != NULL)
      {
        //we know it is of type MyClassB
      }
    }

このようなことは可能ですか?テンプレート型がありますが、実際の型を知りたいですか?

4

3 に答える 3

7

テンプレートの世界では、実行時チェックを行う代わりに、型ごとにテンプレートを特殊化するだけでよいでしょう。

 template<typename T>
 void foo(T obj);

 template<>
 void foo<MyClassA>(MyClassA obj) {
 }

 template<>
 void foo<MyClassB>(MyClassB obj2) {
 }

これにより、コンパイラは引数を推測することにより、コンパイル時に正しいテンプレートを生成できます。

これは、インスタンスの static type に基づいてのみ解決されることに注意してください。つまり、変数がMyClassCから継承されるMyClassBため、ジェネリック形式を使用する必要があるというコンパイル時の知識はありません。したがって、これは機能しません:

  MyClassC* cinstance = new MyClassC();
  foo(cinstance); //compiler error, no specialization for MyClassC

一般に、これは、コンパイル時ポリモーフィズムと実行時ポリモーフィズムが非常に異なるシステムであるという一般的なルールを示しています。テンプレートは、継承の知識がなくても静的な型の領域を厳密に扱います。これは、2 つの機能がよりシームレスに統合されている Java/C# から来た人々を驚かせるかもしれません。

クラスの機能を実行時に特化する場合、オプションは次のとおりです。

  1. 仮想メソッドの定義 -- この機能の一部が本当にこのオブジェクトの一部であるかどうかによっては、適切ではない可能性があります
  2. dynamic_cast (あなたが現在行っていること) を使用してください。やや眉をひそめていますが、誰もが得られる最も簡単な解決策になる可能性があります。
  3. ビジター パターン-- オーバーロードを使用して、実行時に正しい型の関数に解決する設計パターン。
于 2013-01-10T20:15:43.367 に答える
4

可能ですがMyClassA、動作させるにMyClassB は少なくとも 1 つの仮想メンバー関数が必要ですdynamic_cast。また、関数のシグネチャでT* genericObjectはなく( ) を実際に使用したいと考えています(それ以外の場合はほとんど意味がありません)。T genericObject

テンプレートの特殊化に基づくソリューションは、静的ポリモーフィズムには問題ありませんが、問題は、入力の型の実行時の検出を有効にする方法だと思います。MyClassA テンプレートが のスーパークラスまたはのスーパークラスである型のポインタで呼び出されていると想像しますMyClassBこの場合、テンプレートの特殊化は正しい答えを提供できません。

とにかく、あなたが達成したいこと(それが何であれ)を達成するために間違ったことをしようとしていると私は強く感じています。この種の質問を投稿するときは、どこに行きたいのか、何を目指しているのかを明確にすることをお勧めますこれは、間違った道に沿った障害物である可能性があります。

于 2013-01-10T20:24:21.663 に答える
1

はい、これは可能です。動的キャストは実行時に発生し、テンプレートはコンパイル中にコードを生成することに注意してください。したがって、関数は引き続き生成されますが、説明したケースについて実行時にチェックを行います。

編集:あなたがやろうとしていることをする正しい方法については、Doug T.の答えを見てください。

于 2013-01-10T20:16:17.740 に答える