頻繁に実行されるメソッドで動的キャストを使用しますか?オーバーヘッドが大きいですか?
dynamic_castによって返されるポインタは正確には何ですか。同じアドレスへのポインタ?別のインスタンスへのポインタ?私はこの理解が不足しています。より具体的には-実行時に息子タイプへのポインターであることが判明した場合にのみ、父タイプのポインターに割り当てたい割り当てがあります。ソリューション?
ありがとうございました。
頻繁に実行されるメソッドで動的キャストを使用しますか?オーバーヘッドが大きいですか?
dynamic_castによって返されるポインタは正確には何ですか。同じアドレスへのポインタ?別のインスタンスへのポインタ?私はこの理解が不足しています。より具体的には-実行時に息子タイプへのポインターであることが判明した場合にのみ、父タイプのポインターに割り当てたい割り当てがあります。ソリューション?
ありがとうございました。
dynamic_cast
ダウンキャストの実行中に有効性を確認するのに役立ちます。
std::bad_cast
ポインタまたは参照を安全にダウンキャストできない場合は、NULLを返すか、例外(参照の場合)をスローします。
頻繁に実行されるメソッドで動的キャストを使用しますか?オーバーヘッドが大きいですか?
キャストの有効性を判断するためにdynamic_cast
いくつかの追加を使用しますRTTI(Run Time Type Information)
したがって、確かにオーバーヘッドがあります。通常、のポインタtypeinfo
にtype
追加されますvirtual table
。仮想メカニズム自体はコンパイラの実装に依存する詳細であるため、通常は言います(コンパイラによって異なる場合があります)。
dynamic_cast
呼び出しによってコードのパフォーマンスが低下するかどうかを判断するには、いくつかの優れたプロファイリングツールを使用してコードをプロファイリングする必要があります。
によって返されるポインタは正確には何ですかdynamic_cast
。同じアドレスへのポインタ?別のインスタンスへのポインタ?
ダウンキャスティングをdynamic_cast
分析する代わりに、アップキャスティングを分析すると、理解しやすくなります。から継承するタイプbase
と別のタイプを指定すると、タイプにはタイプのサブオブジェクトが含まれます。オブジェクトへのポインタがへのポインタにアップキャストされると、操作の結果は内のサブオブジェクトのアドレスになります。実行すると、その操作が元に戻り、引数として渡されたアドレスにサブオブジェクトを含むオブジェクトへのポインターが返されます(同じことを行いますが、ランタイムタイプを実際にチェックせずに可能なオフセットを適用します)。derived
base
derived
base
derived
base
base
derived
dynamic_cast
derived
base
static_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;
}
プログラムは、を出力true
しfalse
ます。void*
ポインタを比較する場合は、ポインタの1つを明示的にキャストする必要があることに注意してください。そうしないと、コンパイラは暗黙のアップキャスト、ダウンキャストポインタを実行します。
メソッドが「頻繁に実行される」かどうかは関係ありません。実行することが、必要なパフォーマンスに重大な悪影響を与える場合に限ります。それを見つける唯一の方法は、コードのプロファイルを作成することです。
返されるポインタは単なるポインタです。質問の後半を明確にするために、サンプルコードを投稿する必要があります。あなたがこれを意味するならば:
Base * p1 = ....;
Derived * d = dynamic_cast<Derived*>(p1);
if ( d ) {
(*d) = "foobar";
}
Derivedが割り当てをサポートしていれば、それで問題ありません。
頻繁に実行されるメソッドで動的キャストを使用しますか?オーバーヘッドが大きいですか?
それほど大きなオーバーヘッドはありません。しかし、それはコンパイラのRTTIの実装に依存します。ただし、時期尚早に最適化しないでください。
dynamic_castによって返されるポインタは正確には何ですか。同じアドレスへのポインタ?別のインスタンスへのポインタ?私はこの理解が不足しています。より具体的には-実行時に息子タイプへのポインターであることが判明した場合にのみ、父タイプのポインターに割り当てたい割り当てがあります。ソリューション?
派生クラスのオブジェクトには、その基本クラスのオブジェクトが含まれています。dynamic_castは、これらのオブジェクトの1つへのポインターを返します(クラスが1つの基本クラスのみを継承する場合は通常同じポインターですが、クラスが複数の基本クラスを継承する場合は同じポインターではありません)。ただし、使用するコンパイラによって異なります。
この投稿の承認された回答を参照してください。LinuxでC++アプリケーションをプロファイリングする方法。valgrindを呼び出すためのオプションと、プロファイルの結果を表示するためのアプリケーションが優れたGUIになります。
動的キャストは、引数と同じアドレスでキャストしたタイプのポインターを返すため、同じオブジェクトを指しています。「son」タイプを「father」タイプに動的にキャストする場合、引数が「son」タイプでない場合、動的キャストはstd::bad_cast例外をスローします。
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ポインタが返されます。