2
  1. 頻繁に実行されるメソッドで動的キャストを使用しますか?オーバーヘッドが大きいですか?

  2. dynamic_castによって返されるポインタは正確には何ですか。同じアドレスへのポインタ?別のインスタンスへのポインタ?私はこの理解が不足しています。より具体的には-実行時に息子タイプへのポインターであることが判明した場合にのみ、父タイプのポインターに割り当てたい割り当てがあります。ソリューション?

ありがとうございました。

4

5 に答える 5

6

dynamic_castダウンキャストの実行中に有効性を確認するのに役立ちます。

std::bad_castポインタまたは参照を安全にダウンキャストできない場合は、NULLを返すか、例外(参照の場合)をスローします。

頻繁に実行されるメソッドで動的キャストを使用しますか?オーバーヘッドが大きいですか? キャストの有効性を判断するためにdynamic_castいくつかの追加を使用しますRTTI(Run Time Type Information)したがって、確かにオーバーヘッドがあります。通常、のポインタtypeinfotype追加されますvirtual table。仮想メカニズム自体はコンパイラの実装に依存する詳細であるため、通常は言います(コンパイラによって異なる場合があります)。

dynamic_cast呼び出しによってコードのパフォーマンスが低下するかどうかを判断するには、いくつかの優れたプロファイリングツールを使用してコードをプロファイリングする必要があります。

によって返されるポインタは正確には何ですかdynamic_cast。同じアドレスへのポインタ?別のインスタンスへのポインタ?

ダウンキャスティングdynamic_cast分析する代わりに、アップキャスティングを分析すると、理解しやすくなります。から継承するタイプbaseと別のタイプを指定すると、タイプにはタイプのサブオブジェクトが含まれます。オブジェクトへのポインタがへのポインタにアップキャストされると、操作の結果はのサブオブジェクトのアドレスになります。実行すると、その操作が元に戻り、引数として渡されたアドレスにサブオブジェクトを含むオブジェクトへのポインターが返されます(同じことを行いますが、ランタイムタイプを実際にチェックせずに可能なオフセットを適用します)。derivedbasederivedbasederivedbasebase deriveddynamic_castderivedbasestatic_cast

最も単純なケースでは、単一の(非仮想)継承ではderivedサブオブジェクトが整列されますbaseが、多重継承の場合はそうではありません。

struct base {
   int x;
   virtual void foo() {}
};
struct another_base {
   virtual void bar() {}
};
struct derived : base, another_base {};
int main() {
   derived d;
   base * b = &d;           // points to the base subobject inside derived
   another_base * o = &d;   // points to the another_base subobject inside derived

   std::cout << std::boolalpha
       << ( static_cast<void*>(b) == dynamic_cast<derived*>(b) ) << "\n"
       << ( static_cast<void*>(o) == dynamic_cast<derived*>(o) ) << std::endl;
}

プログラムは、を出力truefalseます。void*ポインタを比較する場合は、ポインタの1つを明示的にキャストする必要があることに注意してください。そうしないと、コンパイラは暗黙のアップキャスト、ダウンキャストポインタを実行します。

于 2011-06-15T07:41:28.850 に答える
1

メソッドが「頻繁に実行される」かどうかは関係ありません。実行することが、必要なパフォーマンスに重大な悪影響を与える場合に限ります。それを見つける唯一の方法は、コードのプロファイルを作成することです。

返されるポインタは単なるポインタです。質問の後半を明確にするために、サンプルコードを投稿する必要があります。あなたがこれを意味するならば:

Base * p1 = ....;

Derived * d = dynamic_cast<Derived*>(p1);
if ( d ) {
     (*d) = "foobar";
}

Derivedが割り当てをサポートしていれば、それで問題ありません。

于 2011-06-15T07:41:43.683 に答える
1

頻繁に実行されるメソッドで動的キャストを使用しますか?オーバーヘッドが大きいですか?

それほど大きなオーバーヘッドはありません。しかし、それはコンパイラのRTTIの実装に依存します。ただし、時期尚早に最適化しないでください。

dynamic_castによって返されるポインタは正確には何ですか。同じアドレスへのポインタ?別のインスタンスへのポインタ?私はこの理解が不足しています。より具体的には-実行時に息子タイプへのポインターであることが判明した場合にのみ、父タイプのポインターに割り当てたい割り当てがあります。ソリューション?

派生クラスのオブジェクトには、その基本クラスのオブジェクトが含まれています。dynamic_castは、これらのオブジェクトの1つへのポインターを返します(クラスが1つの基本クラスのみを継承する場合は通常同じポインターですが、クラスが複数の基本クラスを継承する場合は同じポインターではありません)。ただし、使用するコンパイラによって異なります。

于 2011-06-15T07:54:09.827 に答える
0
  1. この投稿の承認された回答を参照してください。LinuxでC++アプリケーションをプロファイリングする方法。valgrindを呼び出すためのオプションと、プロファイルの結果を表示するためのアプリケーションが優れたGUIになります。

  2. 動的キャストは、引数と同じアドレスでキャストしたタイプのポインターを返すため、同じオブジェクトを指しています。「son」タイプを「father」タイプに動的にキャストする場合、引数が「son」タイプでない場合、動的キャストはstd::bad_cast例外をスローします。

于 2011-06-15T07:45:05.063 に答える
0

dynamic_castによって返されるポインタは正確には何ですか。同じアドレスへのポインタ?別のインスタンスへのポインタ?私はこの理解が不足しています。より具体的には-実行時に息子タイプへのポインターであることが判明した場合にのみ、父タイプのポインターに割り当てたい割り当てがあります。

あなたが持っているとしましょう

class Base { ... };
class ChildA : public Base { ... };
class ChildB : public Base { ... };

ChildA childa;
ChildB childb;

Base * ptra = &childa;
Base * ptrb = &childb;

ChildA * ptra_as_ChildA = dynamic_cast<ChildA*>(ptra); // == &childa
ChildA * ptrb_as_ChildA = dynamic_cast<ChildA*>(ptrb); // == NULL

指示されたオブジェクトがターゲットクラスのインスタンスまたはターゲットクラスから派生したクラスである場合、dynamic_castはnull以外のポインタを返します。ポイントされたオブジェクトがターゲットクラスのインスタンスでない場合は、nullポインタを返します。

注:dynamic_castへのポインタ入力が指す正確なメモリ位置とdynamic_castが返すポインタは同じでない場合があります。例:ChildAがBaseとSomeInterfaceの2つのクラスから継承するとします。ChildAポインターをBaseポインターおよびSomeInterfaceポインターにstatic_castできます。これらの2つの親クラスポインタの少なくとも1つは、ChildAポインタと同じメモリ位置を指していません。これらの2つの親クラスポインタのいずれかを動的にキャストすると、元のChildAポインタが返されます。

于 2011-06-15T08:27:16.473 に答える