reinterpret


原文地址https://www.cnblogs.com/xiangtingshen/p/11063805.html

reinterpret意為“重新解釋”

reinterpret_cast是C++中與C風格類型轉換最接近的類型轉換運算符。它讓程序員能夠將一種對象類型轉換為另一種,不管它們是否相關。

reinterpret_cast用在任意指針(或引用)類型之間的轉換以及指針與足夠大的整數類型之間的轉換;從整數類型(包括枚舉類型)到指針類型,無視大小。

(所謂"足夠大的整數類型",取決於操作系統的參數,如果是32位的操作系統,就需要整形(int)以上的;如果是64位的操作系統,則至少需要長整形(long)。具體大小可以通過sizeof運算符來查看)。

【注意】reinterpret_cast不能用於內置類型之間的轉換,只能用於不同指針之間的轉換。

CBase* pBase = new CBase( ) ;  
CDerived* pDerived = reinterpret_cast<CDerived*>(pBase) ;  

這種類型轉換實際上是強制編譯器接受static_cast通常不允許的類型轉換,它並沒有改變指針值的二進制表示,只是改變了編譯器對源對象的解釋方式。

【應盡量避免使用reinterpret_cast】

 

reinterpret_cast  VS  static_cast

static_cast主要管:有繼承關系類的指針和內置數據類型的轉換(和C的內置類型轉換規則一致,可能改變底層的位,也可能不改變)。

reinterpret_cast主要管:所有指針(引用)之間的轉換

 

在它們管理的交叉點處——有繼承關系的指針的轉換,處理方式有所不同。

 

static_cast和reinterpret_cast的區別主要在於多重繼承

 

復制代碼
class A  
{  
public:  
    int m_a;  
};  
class B  
{  
public:  
    int m_b;  
};  
class C : public A, public B {};  
  
C c;  
printf("%p, %p, %p", &c, reinterpret_cast<B*>(&c), static_cast <B*>(&c));  
復制代碼

 

前兩個的輸出值是相同的,最后一個則會在原基礎上偏移4個字節。

這是因為static_cast計算了父子類指針轉換的偏移量,並將之轉換到正確的地址(c里面有m_a,m_b,轉換為B*指針后指到m_b處),而reinterpret_cast卻不會做這一層轉換。

 

reinterpret_cast  VS  const_cast

reinterpret_cast不能像const_cast那樣去除const修飾符。

復制代碼
int main()   
{  
    typedef void (*FunctionPointer)(int);  
    int value = 21;  
    const int* pointer = &value;  
      
    int * pointer_r = reinterpret_cast<int*> (pointer); //編譯報錯  
      
    FunctionPointer funcP = reinterpret_cast<FunctionPointer> (pointer);  
}  
復制代碼

reinterpret_cast只能改變指針(或引用)的解釋方式,不能把其上的const鎖轉換掉。

 

 

const_cast

const_cast讓程序員能夠關閉對象的訪問修飾符const。

在理想的情況下,程序員將經常在正確的地方使用關鍵字const。

但是現實世界,經常可以看到該使用const的地方沒有使用。

這樣,在外部函數中調用類中的這些成員函數,可能會報錯。

 

 

復制代碼
CSomeClass  
{  
public:  
    ….  
    void DisplayMember( ) ;  
};  
void DisplayAllData( const CSomeClass& mData )  
{  
    mData.DisplayMembers ( ) ; //編譯報錯  
}  
復制代碼

為什么會編譯報錯?

因為DisplayMembers為普通的成員函數,故DisplayMembers成員函數中隱藏的this指針,會被編譯器設置為CSomeClass* this。而mData是被const修飾的,mData.DisplayMembers ( ) ;即是DisplayMembers ( &mData); 這樣,實參和形參類型不一致,編譯器會報錯。

 

如何修改這一問題?

①把函數列表上mData前的const去掉。

這樣,使代碼的安全性降低,其后的代碼可能會修改mData中的值。

②在成員函數DisplayMembers前添上const。

這樣固然最好,但是如果CSomeClass是第三方的類,我們沒有其源代碼,那怎么辦?

③使用const_cast把mData上的const鎖暫時去掉。

void DisplayAllData( const CSomeClass& mData )  
{  
    CSomeClass& refData = const_cast< CSomeClass &>(mData) ;  
    refData.DisplayMembers ( ) ;   
}  

另外:const_cast也可用於指針

void DisplayAllData( const CSomeClass* pData )  
{  
    CSomeClass*  pCastedData = const_cast< CSomeClass *>( pData) ;  
    pCastedData ->DisplayMembers ( ) ;   
} 

C++類型轉換符存在的問題:

static_cast的用途可用C風格類型轉換進行處理,且更簡單。

例:

double dPi = 3.14 ;  
int num1 = static_cast<int>(dPi) ;  
int num2 = (int)dPi ;  
  
CDerived* pDerived1 = static_cast<CDerived*>(pBase) ;  
CDerived* pDerived2 = (CDerived*)pBase ;  

故,Bjarne Stroustrup說:“由於static_cast如此拙劣且難以輸入,因此您在使用它之前很可能會三思。這很不錯,因為類型轉換在現代C++中是最容易避免的。”

因此,在現代C++中,除dynamic_cast外的類型轉換都是可以避免的。

僅當需要滿足遺留應用程序需求時,才需要使用其它類型轉換運算符。在這種情況下,程序員通常傾向於使用C風格類型轉換而不是使用C++類型轉換運算符。

 

重要的是,應盡量避免使用類型轉換,而一旦使用類型轉換,務必要知道幕后發生的情況。

 

關於隱式轉換:

例:

復制代碼
#include <iostream>  
  
using namespace std ;  
  
class A  
{  
    int m_nA ;  
};  
class B  
{  
    int m_nB;  
};  
class C : public A, public B  
{  
    int m_nC;  
};  
  
int main(void)  
{  
    C* pC = new C ;  
    B* pB = dynamic_cast<B*>(pC) ;  
    A* pA = dynamic_cast<A*>(pC) ;  
       
    if ( pC==pB )  
        cout << “equal” << endl ;  
    else  
        cout << “not equal” << endl ;  
  
    if ( (int)pC == (int)pB )  
        cout << “equal” <<endl ;  
    else  
        cout << “not equal” << endl ;  
  
    return 0 ;  
}  
//程序輸出如下:  
//equal  
//not equal  
復制代碼

if ( pC == pB )這里兩端數據類型不同,比較時需要進行隱式類型轉換。( pC == pB )相當於:pC == (C*)pB ;

pB實際上指向的地址是對象C中的子類B的部分,從地址上跟pC不一樣,所以直接比較地址數值的時候是不相同的。故 (int)pC 與(int)pB 不同。

 

但是:(C*)pB相當於static_cast<C*>(pB)

它們計算了父子類指針轉換的偏移量,並將之轉換到正確的地址(c里面有m_a,m_b,轉換為B*指針后指到m_b處)

[請參考這里——C++對象模型簡介]

 

【在C++中,涉及相關指針的強制類型轉換,並不是不改變指針值,有時(涉及多重繼承時)會根據需要改變底層值。reinterpret_cast才是只改變解釋方式,不改變底層值。】

 

【注意】C++中的隱式類型轉換的方式和static_cast的轉換行為類似。(只是static_cast對於不相關指針的轉換無能為力)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM