Sunday, June 13, 2010

reinterpret casting

The "reinterpret_cast" keyword.
  • Operates on references and pointers.
  • It results in only the direct coping of the pointer/reference and nothing more. This means that the exact value being pointed to is unchanged and will be interpreted as the new type directly.
  • The exact way the contents of the pointer are interpreted after conversion is very system dependent.
  • This cast is normally used to convert c++ data structures into something usable by a 3rd party API or lib, or in buffer pools and variable data type implementations. If a chunk of data has multiple interpretations to (like IP headers etc) then a "union" is better choice.

//compile with g++
#include <iostream>
using namespace std;

class BaseA
{
  virtual void print() { cout << "BaseA"; }
};

class DerivedA1 : public BaseA
{
  int a;
  virtual void print() { cout << "DerivedA1"; }
};

class DerivedA2 : public BaseA
{
  virtual void print() { cout << "DerivedA2"; }
};

class DerivedA3 : public DerivedA1
{
  virtual void print() { cout << "DerivedA3"; }
};

class BaseB
{
public:
  BaseB()         { }
  BaseB(BaseA& A) { cout << "Converting BaseA" << endl; }
  virtual void print() { cout << "BaseA"; }
};

int main()
{
  int    int1         = 100;
  double double1      = 3.142;

  cout << "reinterpret casting: non-conversion of data example " << endl;
  char*      char1    = reinterpret_cast<char*>(&int1);  //OK keep in mind the endianess of the system
  int*       int2     = reinterpret_cast<int*>(&double1); //OK be aware of the proceses native double formats

  cout << "reinterpret_cast<char>(int1)  " << *char1 << " <- " << int1    << endl;
  cout << "reinterpret_cast<int>(double) " << *int2  << " <- " << double1 << endl;
  cout << endl;

  BaseA*     base1    = new BaseA();
  BaseB*     baseB    = new BaseB();
  BaseA*     base2    = new DerivedA2();
  BaseA*     base3    = new DerivedA3();
  DerivedA3* derived1 = new DerivedA3();

  cout << "reinterpret casting: pointers " << endl;
  DerivedA1* derived2 = reinterpret_cast<DerivedA1*>(base1);  //BAD base1 doesnt have the correct memory to be DerivedA1 class!   
  DerivedA1* derived3 = reinterpret_cast<DerivedA1*>(base2);
  DerivedA2* derived4 = reinterpret_cast<DerivedA2*>(base2);
  DerivedA1* derived5 = reinterpret_cast<DerivedA1*>(base3);
  BaseA*     base4    = reinterpret_cast<BaseA*>(derived1);   //OK but overkill

  char*      charPtr  = reinterpret_cast<char*>(&int1);     //OK but be careful int and char dont share any inhertance.
  BaseB*     base5    = reinterpret_cast<BaseB*>(derived1); //BAD BaseB and dervied1 have conflicting memory layouts 

  cout << "reinterpret casting: references " << endl;
  DerivedA1& refDerived1    = reinterpret_cast<DerivedA1&>(*base1); //BAD base1 doesnt have the correct memory to be DerivedA1 class! 
  DerivedA1& refDerived2 = reinterpret_cast<DerivedA1&>(*base2);
  DerivedA2& refDerived3 = reinterpret_cast<DerivedA2&>(*base2);
  DerivedA1& refDerived4 = reinterpret_cast<DerivedA1&>(*base3);
  BaseA& refBase         = reinterpret_cast<BaseA&>(*derived1);
  BaseB& refBaseB        = reinterpret_cast<BaseB&>(*derived1); //BAD BaseB and dervied1 have conflicting memory layouts 

  delete base1;
  delete baseB;
  delete base2;
  delete base3;
  delete derived1;
}

No comments:

Post a Comment