5

基本クラスといくつかの派生クラスがあるとしましょう。次のようなものを書く必要なく、派生クラスの 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 {
  ...
}
4

8 に答える 8

22

しないでください。

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

動的キャストで行う決定は、すでに行われています。実際の作業をサブクラスに委任するだけです。

例の最も重要な部分を省略しました。便利で多様な作品。

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();
于 2008-10-28T12:49:43.453 に答える
9

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

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

于 2008-10-28T12:34:56.760 に答える
5
Derived1* d1 = dynamic_cast< Derived1* >(object);
if (d1 == NULL)
{
    Derived2* d2 = dynamic_cast< Derived2* >(object);
    //etc
}

C# の「is」と「as」をシミュレートする、smartpointer 型に次のメソッドがあります。

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);}
于 2008-10-28T12:38:48.607 に答える
4

を使用してこれを行うことができます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.
}

しかし、他の人が言ったように、このようなコードは設計が悪いことを示している可能性があり、通常は仮想関数を使用してポリモーフィックな動作を実装する必要があります。

于 2008-10-28T12:39:28.467 に答える
3

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

于 2008-10-28T12:32:18.230 に答える
2

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

于 2008-10-28T12:35:45.150 に答える
1

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

于 2008-10-28T13:17:22.553 に答える
1

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

于 2008-10-28T12:34:21.830 に答える