static_cast<> reinterpret_cast < > 비밀 폭로

상세 한 토론 은 다음 과 같다.
http://www.cnblogs.com/ider/archive/2011/08/01/cpp_cast_operator_part5.html
http://www.cnblogs.com/ider/archive/2011/07/30/cpp_cast_operator_part4.html
http://www.cnblogs.com/ider/archive/2011/07/31/cpp_cast_operator_part3.html
http://www.cnblogs.com/ider/archive/2011/07/31/cpp_cast_operator_part2.html
 
본문 토론 staticcast < > 와 reinterpretcast<>。
대부분의 프로그래머 들 이 C + + 를 배우 기 전에 C 를 배 웠 고 C 스타일 (유형) 전환 에 익숙 하 다 고 소개 했다.C + + (프로그램) 을 쓸 때, 때때로 우 리 는 static 를 사용한다cast < > 와 reinterpretcast < > 시 약간 모호 할 수 있 습 니 다.본문 에서 나 는 static 를 설명 할 것 이다.cast < > 는 실제로 무엇 을 했 는 지, 그리고 잘못된 상황 을 지적 합 니 다.범용 (Generic Types)
요컨대 staticcast < > 변환 을 시도 합 니 다. 예 를 들 어 float - integer, reinterpretcast < > 컴 파 일 러 의 의 도 를 간단하게 바 꾸 어 그 대상 을 다른 유형 으로 다시 고려 합 니 다.
포인터 종류 (포인터 종류)
포인터 전환 이 좀 복잡 합 니 다. 우 리 는 본 고의 나머지 부분 에서 다음 과 같은 종 류 를 사용 할 것 입 니 다.
        float f = 12.3;

        float* pf = &f;
      

// static cast<> // , n = 12 int n = static_cast<int>(f); // , ( : pf float , int ) //int* pn = static_cast<int*>(pf); // void* pv = static_cast<void*>(pf); // , *pn2 (rubbish) int* pn2 = static_cast<int*>(pv);

// reinterpret_cast<> // , static_cast<> //int i = reinterpret_cast<int>(f); // , *pn , *pn2 int* pi = reinterpret_cast<int*>(pf);


상황 1: 두 개의 무관 한 클래스 간 의 전환
4. 567913. 우리 가 일반적인 예 에서 알 고 있 듯 이 한 대상 을 다른 무관 한 클래스 static 로 전환 하려 고 한다 면cast < > 는 실패 하고 reinterpretcast < > 는 항상 '사기' 컴 파일 러 에 성공 합 니 다. 그 대상 은 바로 그것 과 무관 합 니 다.
상황 2: 관련 클래스 로 전환
class CBaseX

      {

      public:

      int x;

      CBaseX() { x = 10; }

      void foo() { printf("CBaseX::foo() x=%d
", x); } };

class CBaseY { public: int y; int* py; CBaseY() { y = 20; py = &y; } void bar() { printf("CBaseY::bar() y=%d, *py=%d
", y, *py); } };

class CDerived : public CBaseX, public CBaseY { public: int z; };

      // Convert between CBaseX* and CBaseY*

      // CBaseX*   CBaseY*     

      CBaseX* pX = new CBaseX();

      // Error, types pointed to are unrelated

      //   ,         

      // CBaseY* pY1 = static_cast<CBaseY*>(pX);

      // Compile OK, but pY2 is not CBaseX

      //     ,    pY2   CBaseX

      CBaseY* pY2 = reinterpret_cast<CBaseY*>(pX);

      // System crash!!

      //     !!

      // pY2->bar();

메모: CDerived * 를 암시 적 static 로 사용 합 니 다.cast < > 가 CBasey * (다섯 번 째 줄) 로 전환 되 었 을 때 결 과 는 (가리 키 는) CDerived * (포인터 가 뒤로) 4 (바이트) 로 이동 하 였 습 니 다.static 를 알 기 위해cast < > 실제 상황 이 어 떻 습 니까? CDerived 의 메모리 레이아웃 을 살 펴 봐 야 합 니 다.
CDerived 의 메모리 레이아웃 (Memory Layout) 은 그림 에서 보 듯 이 CDerived 의 메모리 레이아웃 은 두 개의 대상 을 포함 하고 CBaseX 와 CBaseY, 컴 파일 러 도 이 점 을 알 고 있다.따라서 CDerived * 를 CBasey * 로 변환 할 때 포인터 에 4 개의 바이트 를 추가 하고 CBasey * 를 CDerived * 로 변환 할 때 포인터 에 4 를 빼 줍 니 다.하지만 CDerived 가 아니 더 라 도 그 럴 수 있 습 니 다.물론 이 문 제 는 당신 이 더 많은 상속 을 했 을 때 만 발생 합 니 다.CDerived 를 CBasex 로 변환 할 때 staticcast < > 와 reinterpretcast < > 는 다 를 바 가 없습니다.상황 3: void * 사이 의 앞 과 뒤로 전환 은 모든 포인터 가 void * 로 바 뀔 수 있 기 때문에 void * 는 뒤로 모든 포인터 로 전환 할 수 있 습 니 다. (static cast < > 와 reinterpret cast < > 변환 은 모두 이렇게 할 수 있 습 니 다) 조심 하지 않 으 면 오류 가 발생 할 수 있 습 니 다.
      1. CDerived* pD = new CDerived();

      2. printf("CDerived* pD = %x
", (int)pD); 3. 4. // static_cast<> CDerived* -> CBaseY* -> CDerived* // , static_cast<> 5. CBaseY* pY1 = pD; 6. printf("CBaseY* pY1 = %x
", (int)pY1); // , pD1 = pD 7. CDerived* pD1 = static_cast<CDerived*>(pY1); 8. printf("CDerived* pD1 = %x
", (int)pD1); 9. 10. // reinterpret_cast // , pY2 CBaseY* 11. CBaseY* pY2 = reinterpret_cast<CBaseY*>(pD); 12. printf("CBaseY* pY2 = %x
", (int)pY2); 13. 14. // static_cast<> 15. CBaseY* pY3 = new CBaseY(); 16. printf("CBaseY* pY3 = %x
", (int)pY3); // , pY3 " CBaseY()" 17. CDerived* pD3 = static_cast<CDerived*>(pY3); 18. printf("CDerived* pD3 = %x
", (int)pD3);
      ----------------------    ---------------------------

      CDerived* pD = 392fb8

      CBaseY* pY1 = 392fbc

      CDerived* pD1 = 392fb8

      CBaseY* pY2 = 392fb8

      CBaseY* pY3 = 390ff0

      CDerived* pD3 = 390fec

      

일단 우리 가 지침 을 void * 로 바 꾸 었 다 면, 우 리 는 쉽게 그것 을 원류 로 바 꿀 수 없다.위의 예 에서 하나의 void * 에서 CDerived * 로 돌아 가 는 유일한 방법 은 CBasey * 로 전환 한 다음 에 CDerived * 로 전환 하 는 것 입 니 다.그러나 만약 우리 가 그것 이 CBasey * 인지 CDerived * 인지 확실 하지 않다 면, 우 리 는 어 쩔 수 없 이 dynamiccast < > 또는 typeid [2].주석: 1. dynamiccast < >, 다른 한편 으로 는 일반적인 CBasey * 가 CDerived * 로 전환 되 는 것 을 방지 할 수 있 습 니 다.2. dynamic_cast < > 는 클래스 가 다 중, 즉 '허' 함 수 를 포함 하고 이 로 인해 void * 가 될 수 없습니다.참고: 1. [MSDN] C + + Language Reference -- Casting 2. Nishant Sivakumar, Casting Basic - Use C + + casts in your VC + +. NET programs 3. Juan Soulie, C + + Language Tutorial: Type Casting 추천 링크: 실행 중 대상 유형 을 확인 하 는 방법 (RTTI)

좋은 웹페이지 즐겨찾기