質問

Base クラスといくつかの Derived クラスがあるとします。このような何かを書く必要なしに、派生クラスの1つにオブジェクトをキャストする方法はありますか:


string typename = typeid(*object).name();
if(typename == "Derived1") {
   Derived1 *d1 = static_cast< Derived1*>(object);
}
else if(typename == "Derived2") {
   Derived2 *d2 = static_cast < Derived2*>(object);
}
...
else {
  ...
}
役に立ちましたか?

解決

しないでください。

ポリモーフィズムについて読んでください。ほとんどすべての「ダイナミックキャスト」状況は、実装に苦労しているポリモーフィズムの例です。

ダイナミックキャストで行う決定はすべて既に行われています。実際の作業をサブクラスに委任するだけです。

例の最も重要な部分は省略しました。有用な多態性の仕事。

string typename = typeid(*object).name();
if(typename == "Derived1") {
   Derived1 *d1 = static_cast< Derived1*>(object);
   d1->doSomethingUseful();
}
else if(typename == "Derived2") {
   Derived2 *d2 = static_cast < Derived2*>(object);
   d2->doSomethingUseful();
}
...
else {
  ...
}

すべてのサブクラスがdoSomethingUsefulを実装している場合、これはすべてずっと簡単です。そしてポリモーフィック。

object->doSomethingUseful();

他のヒント

dynamic_cast を使用してNULLをテストできますが、代わりに強くコードをリファクタリングすることを検討します。

サブクラス固有の処理が必要な場合、テンプレートメソッドは役立つかもしれませんが、知らないままです。あなたが達成しようとしているもの、それは漠然とした推測にすぎません。

Derived1* d1 = dynamic_cast< Derived1* >(object);
if (d1 == NULL)
{
    Derived2* d2 = dynamic_cast< Derived2* >(object);
    //etc
}

C#の「is」と「as」をシミュレートするスマートポインタータイプには次のメソッドがあります:

template< class Y > bool is() const throw()
    {return !null() && dynamic_cast< Y* >(ptr) != NULL;}
template< class Y > Y* as() const throw()
    {return null() ? NULL : dynamic_cast< Y* >(ptr);}

dynamic_cast を使用してこれを行うことができます。例:

if ( Derived1* d1 = dynamic_cast<Derived1*>(object) ) {
    // object points to a Derived1
    d1->foo();
}
else if ( Derived2* d2 = dynamic_cast<Derived2*>(object) ) {
    // object points to a Derived2
    d2->bar();
}
else {
    // etc.
}

しかし、他の人が言ったように、このようなコードは悪いデザインを示している可能性があり、通常は仮想関数を使用して、多態的な動作を実装します。

通常、これは悪い設計のサインです。なぜこれを行う必要があるのですか?これが不要になるように再設計することが可能かもしれません。

正確に何を達成しようとしていますか? 私の経験では、このようなことはデザインが悪いことを示しています。オブジェクト指向設計の目標はこのようなことを不要にすることなので、クラス階層を再評価してください。

name()の正確な形式が指定されていないため、この例は移植されません。一連の dynamic_cast を試すことができます。 Dynamic_cast は、間違った型にキャストするとnullポインターを返します。ただし、このようなタイプ切り替えを行っている場合は、設計に問題があります。

dynamic_castを使用する方法だと思いますが、キャストするオブジェクトはサードパーティモジュールによって提供されるものである可能性があるため、これが考えられるすべての条件に対して悪い設計だとは特に思いません。オブジェクトの作成者が知識のないプラグインによって作成されたとしましょう。そして、その特定のプラグインは、Derived1(古いバージョンである)タイプオブジェクトまたはDerived2(新しいバージョンである)タイプオブジェクトを作成できます。プラグインインターフェイスはバージョン固有のものを実行するように設計されていない可能性があります。オブジェクトを作成するだけなので、アプリケーションは適切なキャスト/実行を確認するためにこの種のチェックを行う必要があります。この後、安全にobject.doSomethingUsefulThatDoesNotExistInDerived1();を呼び出すことができます

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top