2013-07-01 6 views
7

基本クラスがgameObjectで、派生クラスがanimatedGameObjectであるとすれば、すべてのインスタンスをstd::vectorに保存するとよいかもしれないと考えました。ベクトルGameObjectsが基本型gameObject*であると宣言されている場合、派生オブジェクトインスタンスはキャストが必要です。static_castを使用して混合(ベース&派生)オブジェクトのベクトルを処理する場合のパフォーマンス上のリスクはありますか?

例:

多くのプログラマは、キャストが何もしないことを信じている:

vector<gameObject*> GameObjects; 

gameObject A* = new gameObject(...init...); 
animatedGameObject B* = new animatedGameObject(...init...); 

GameObjects.push_back(A); 
GameObjects.push_back(B); 

// to access the animatedGameObject functions: 
static_cast<animatedGameObject*>(GameObjects[1])->functionUniqueToAnimated(); 

は通常通り怖いので、私は、件名に書き込みスコット・マイヤーズ(効果的なC++第3版)、になりましたあるタイプを別のタイプとして扱うようにコンパイラに指示しますが、これは間違いです。あらゆる種類の型変換(キャストによる明示的またはコンパイラによる暗黙的)は、実行時に実行されるコードにつながることがよくあります。

私は彼の項目27を介して読んだ:二回鋳造最小化、まだこれで私の経験不足を与えられ、私は簡単な質問答えるために私のできないことに苦しんでいます「これが行うことをDUMB事ですか?」

私はそれstatic_castを呼び出すこととは何の関係もないことを行うにダムの事あるいくつかの理由があることを言及する必要があります。質問は、重要度順に、以下のとおりです。私は上記の私の例ではstatic_castを使用して、いくつかの可能性のあるリスクを見ていない

  1. アム?
  2. このようなアプローチでは、std::vectorよりも優れたデータ構造がありますか? (明白なものがある場合のみ、私に研究を依頼しているわけではありません)

これは私の最初の質問です。

+0

+1のために有効なC++ – Borgleader

+1

ここで行うべきことは、 'draw()'を基本クラスの仮想関数として定義することです。あなたは単にキャストなしでそれを呼び出すことができ、それは正しいことをするでしょう。あなたはこれに気付いていますが、キャストの効果について具体的に知りたいですか? – jogojapan

+1

'boost :: ptr_vector' – Mehrdad

答えて

7

static_castは、gameObjectではなく、animatedGameObjectにポインタが移動していることがわかっている場合を除き、適切なツールではありません。その情報を格納するために使用するデータ構造は何ですか?

ベースポインタがダイナミックディスパッチのジョブの後に派生オブジェクトの型を決定するか、dynamic_castです。あなたの例では、drawが仮想関数でなければならないので、GameObjects[1]->draw()コールはキャストなしで動作するはずです。それ以外の場合は、dynamic_cast< animatedGameObject & >(* GameObjects[1])を使用してオブジェクトがanimatedGameObjectであることをアサートし、そうでない場合はstd::bad_cast例外をスローすることができます。 (これはまだclass gameObjectvirtual機能、通常、そのデストラクタが必要になります。)

しかし、多型派生型にstatic_castを行うと、コードのにおいです。


また、あなたはstd::vectorは、このユースケースのための良好なデータ構造であるかどうかを尋ねます。それは "裸の"ポインタのベクトルではありません。 C++ 11では、newdeleteを実行する「スマートポインタ」メモリ管理クラスが提供され、実際の演算子はすべて廃止されました。この場合、std::unique_ptrを参照してください。

+1

私はちょうど別の投票/バーチャルを描くためのより多くの可視性を持っていますので、これはキャストせずに行うことができます。これは仮想関数が本質的に完全に機能するものの古典的な例の1つです。 –

+1

@jogojapan D'oh、私は自分自身を混乱させる。カスタムディレターは、 'unique_ptr'が非多型型を多態的に扱えるようにすることができます。修正されます。 – Potatoswatter

+0

ありがとうございました。 'std :: shared_ptr'を読むつもりです – ilzxc

1
  1. gameObjects [1]がanimatedGameObjectでない場合、アプリケーションは恐らくひどく死ぬでしょう。
  2. drawObjectがgameObjectに存在する仮想メソッドである場合、変換は不要です。

一般に、派生クラスへの基底クラスのキャストは安全ではありません。そのような状況では、dynamic_castを使用するのが理にかなっています。変換が実行できない場合、Dynamic_castはNULLを返します。

よりも優れたデータ構造は、あなたのゲームオブジェクトが自動的に別の場所に削除されていない場合はまあ、それはstd::vector<std::shared_ptr<gameObject> >ようなものを使用する意味がある場合がございます。しかし、標準の共有ポインタは隠されたオーバーヘッドを招く可能性があります(余分な新規/削除、最悪の場合はマルチスレッドのミューテックスロックを導入することさえあり、スレッドセーフであるように設計されています)。目標。