C++演算子のタイプ変換
3445 ワード
一、const_cast:タイプ修飾子const,volatileのみに影響
使用法:const_cast(expression)
この演算子は、タイプのconstまたはvolatileプロパティを変更するために使用します.constまたはvolatile修飾に加えてtype_idとexpressionのタイプは同じです.定数ポインタは、非常量ポインタに変換され、元のオブジェクトを指す. 定数参照は、非常量参照に変換され、元のオブジェクトを指す. 定数オブジェクトは、非常量オブジェクトに変換される.
二、static_cast:クラス階層におけるベースクラス(親)と派生クラス(子)との間のポインタまたは参照の変換に使用します.アップリンク変換(派生クラスのポインタまたは参照をベースクラス表現に変換)を行うのは安全です.ダウンリンク変換(ベースクラスポインタまたは参照を派生クラス表現に変換)を行う場合、ダイナミックタイプチェックがないため安全ではありません. は、intをcharに変換し、intをenumに変換するなどの基本データ型間の変換に使用される.このような転換の安全性も開発者が保証しなければならない. 空ポインタをターゲットタイプの空ポインタに変換します. は、任意のタイプの式をvoidタイプに変換する.
注意:static_キャストはexpressionのconst、volatile、または__を変換できません.unalignedプロパティ.
C++のstatic_castは、Cにおける通常の変換動作の代わりに非多態変換を実行する.C変換と同じ威力と意味を持ち、同じ制限を持っている.たとえばstatic_は使えませんcastはstructをintに変換するか、doubleをpointerに変換します.
三、reinterpret_cast:オペレータはオペランドタイプを変更したが、バイナリ変換を行わずに与えられたオブジェクトのビットモデルを再解釈しただけである. すべてのマッピングで最も危険です. で最も一般的な用途は、「関数ポインタ」タイプを変換することです.たとえば、 です. static_castとreinterpret_castの違いは主に のような多重継承にある.
では、次のコードについて説明します.
最初の2つの出力値は同じで、最後の2つはstatic_castは、親子ポインタ変換のオフセット量を計算し、正しいアドレス(cにはm_a,m_bがあり、B*ポインタに変換してm_bを指す)に変換しますが、reinterpret_castはこのレベルの変換をしません.
四、dynamic_cast: dynamic_cast演算子は、実行期間中に真のタイプを決定できます.downcastが安全である場合(すなわち、ベースクラスポインタまたは参照が派生クラスオブジェクトを指している場合)この演算子は、適切に変換されたポインタを返します.downcastが失敗すると、この演算子は空のポインタ(変換オブジェクトがポインタである場合)またはexception(変換オブジェクトが参照である場合)を返します. クラス階層間でアップリンク変換を行う場合、dynamic_キャストとstatic_castの効果は同じです.下り変換時にdynamic_castにはstatic_よりもタイプチェック機能があります.castの方が安全です. で下向きタイプ変換を行う場合は、虚関数を持つクラスタイプを指すポインタである必要があります.これは、ランタイムタイプチェックにはランタイムタイプ情報が必要であり、この情報はクラスの虚関数テーブルに格納され、虚関数を定義したクラスだけが虚関数テーブルを持つためです. dynamic_を使用castは、実行コストとメモリコストを大幅に削減します.
次の例を参考にして理解してください.
使用法:const_cast
この演算子は、タイプのconstまたはvolatileプロパティを変更するために使用します.constまたはvolatile修飾に加えてtype_idとexpressionのタイプは同じです.
二、static_cast:
注意:static_キャストはexpressionのconst、volatile、または__を変換できません.unalignedプロパティ.
C++のstatic_castは、Cにおける通常の変換動作の代わりに非多態変換を実行する.C変換と同じ威力と意味を持ち、同じ制限を持っている.たとえばstatic_は使えませんcastはstructをintに変換するか、doubleをpointerに変換します.
三、reinterpret_cast:
typedef void (*FuncPtr)();
int doSomething();
FuncPtr funcPtr = reinterpret_cast<FuncPtr>(&doSomething);
classA { public: int m_a;};
classB { public: int m_b;};
classC : public A, public B {};
では、次のコードについて説明します.
C c;
printf("%p,%p, %p\r
", &c,
reinterpret_cast<B*>(&c),
static_cast<B*>(&c) );
最初の2つの出力値は同じで、最後の2つはstatic_castは、親子ポインタ変換のオフセット量を計算し、正しいアドレス(cにはm_a,m_bがあり、B*ポインタに変換してm_bを指す)に変換しますが、reinterpret_castはこのレベルの変換をしません.
四、dynamic_cast:
次の例を参考にして理解してください.
Base b;
00291A8B lea ecx,[b]
00291A8E call Base::Base (291131h)
Base* pb = NULL;
00291A93 mov dword ptr [pb],0
Derived d;
00291A9A lea ecx,[d]
00291A9D call Derived::Derived (2911C7h)
Derived* pd = NULL;
00291AA2 mov dword ptr [pd],0
pb = &d;
00291AA9 lea eax,[d]
00291AAC mov dword ptr [pb],eax
pd = static_cast<Derived*>(pb);
00291AAF mov eax,dword ptr [pb]
00291AB2 mov dword ptr [pd],eax
pd = dynamic_cast<Derived*>(pb);
00291AB5 push 0
00291AB7 push offset Derived `RTTI Type Descriptor' (29A018h)
00291ABC push offset Base `RTTI Type Descriptor' (29A000h)
00291AC1 push 0
00291AC3 mov eax,dword ptr [pb]
00291AC6 push eax
00291AC7 call @ILT+640(___RTDynamicCast) (291285h)
00291ACC add esp,14h
00291ACF mov dword ptr [pd],eax