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:
  • オペレータはオペランドタイプを変更したが、バイナリ変換を行わずに与えられたオブジェクトのビットモデルを再解釈しただけである.
  • すべてのマッピングで最も危険です.
  • で最も一般的な用途は、「関数ポインタ」タイプを変換することです.たとえば、
  • です.
    typedef void (*FuncPtr)();
    
    int doSomething();
    
    FuncPtr funcPtr = reinterpret_cast<FuncPtr>(&doSomething);
  • static_castとreinterpret_castの違いは主に
  • のような多重継承にある.
    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:
  • dynamic_cast演算子は、実行期間中に真のタイプを決定できます.downcastが安全である場合(すなわち、ベースクラスポインタまたは参照が派生クラスオブジェクトを指している場合)この演算子は、適切に変換されたポインタを返します.downcastが失敗すると、この演算子は空のポインタ(変換オブジェクトがポインタである場合)またはexception(変換オブジェクトが参照である場合)を返します.
  • クラス階層間でアップリンク変換を行う場合、dynamic_キャストとstatic_castの効果は同じです.下り変換時にdynamic_castにはstatic_よりもタイプチェック機能があります.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