// ==========================================================================
// $Id: 08reinterpret_cast.cc,v 1.11 2007/06/20 21:42:27 hitoshi Exp $
// reinterpret_cast issue
// ==========================================================================
// Copyright (C) 2007 Yamauchi Hitoshi
// ==========================================================================
// $Revision: 1.11 $
// $Date: 2007/06/20 21:42:27 $
// Created by hitoshi, last update by $Author: hitoshi $
// ==========================================================================

#include <cstdio>
#include <iostream>

/**
   \brief base class 0
 */
class Base0 {
public:
  virtual void test0() = 0;
};

/**
   \brief base class 1
 */
class Base1 {
public:
  virtual void test1() = 0;
};

/**
   \brief derived class from both 
 */
class Derived : public Base0, public Base1 {
public:
  virtual void test0(){
    std::cout << "test0" << std::endl;
  }
  virtual void test1(){
    std::cout << "test1" << std::endl;
  }
};


int main(){
  
  Derived * pD = new Derived;
  printf("pD = %x\n", pD);

  // cast Derived to Base0. should be static_cast 
  Base0 * pReinterpretcastedB0 = reinterpret_cast< Base0 * >(pD);
  printf("reinterpret_cast< Base0 * >(pD) = %x\n"
	 "This is wrong, but works coincidentally\n", pReinterpretcastedB0);

  Base0 * pCCastedB0           = (Base0 *)(pD);
  printf("(Base0 *)pD                     = %x\nOK.\n", pCCastedB0);

  Base0 * pStaticcastedB0      = static_cast< Base0 * >(pD);
  printf("static_cast< Base0 * >(pD)      = %x\nThis one is correct.\n", pStaticcastedB0);

  // cast Derived to Base1. should be static_cast 
  Base1 * pReinterpretcastedB1 = reinterpret_cast< Base1 * >(pD);
  printf("reinterpret_cast< Base1 * >(pD) = %x\n"
	 "This is wrong, and an example which does not work.\n", pReinterpretcastedB1);

  Base1 * pCCastedB1           = (Base1 *)(pD);
  printf("(Base1 *)pD                     = %x\nOK.\n", pCCastedB1);

  Base1 * pStaticcastedB1      = static_cast< Base1 * >(pD);
  printf("static_cast< Base1 * >(pD)      = %x\nThis one is correct.\n", pStaticcastedB1);

  // cast Base1 to Derived. should be dynamic_cast 
  Derived * pReinterpretcastedD1 = reinterpret_cast< Derived * >(pStaticcastedB1);
  printf("reinterpret_cast< Derived * >(pStaticcastedB1) = %x\n"
	 "This is wrong, and an example which does not work.\n", pReinterpretcastedD1);
  
  Derived * pCCastedD1           = (Derived *)(pStaticcastedB1);
  printf("(Derived *)pStaticcastedB1                     = %x\nOK.\n", pCCastedD1);

  Derived * pStaticcastedD1      = static_cast< Derived * >(pStaticcastedB1);
  printf("static_cast< Derived * >(pStaticcastedB1)      = %x\nOK.\n", pStaticcastedD1);

  Derived * pDynamiccastedD1     = dynamic_cast< Derived * >(pStaticcastedB1);
  printf("static_cast< Derived * >(pStaticcastedB1)      = %x\nThis is correct.\n", 
	 pStaticcastedD1);

  // integral type conversion through re-interpreting the pointer type 
  std::cout << "----- Integral type (holding some values) conversion -----\n";
  double a = 123.45;
  std::cout << "a = " << a << ", *(reinterpret_cast<int *>(&a)) = " 
	    << *(reinterpret_cast<int *>(&a)) << std::endl;    
  std::cout << "a = " << a << ", *(int *)(&a)                   = " 
	    << *(int *)(&a) << std::endl;    

  std::cout << "----- Test wrong reinterpret_cast -----" << std::endl;
  std::cout << "----- casting Base0 to Derived -----" << std::endl;

  std::cout << "Next is wrong, but may coincidentally work, "
	    << "depending on compiler implementation.\n"
	    << "pReinterpretcastedB0->test0() => ";
  pReinterpretcastedB0->test0(); // wrong, but coincidentally works.
  std::cout << "pCCastedB0          ->test0() => "; 
  pCCastedB0          ->test0();
  std::cout << "pStaticcastedD1     ->test0() => "; 
  pStaticcastedB0     ->test0();

  std::cout << "----- casting Base1 to Derived -----" << std::endl;
  std::cout << "Next is test1(), but output would be wrong!, "
	    << "depending on compiler implementation. "
	    << "most likely, test1() outputs test0.\n";
  std::cout << "pReinterpretcastedB1->test1() => ";  
  pReinterpretcastedB1->test1(); // wrong result.
  std::cout << "pCCastedB0          ->test1() => ";  
  pCCastedB1          ->test1();
  std::cout << "pStaticcastedB0     ->test1() => ";  
  pStaticcastedB1     ->test1();

  // Casting Derived to Base1 is more problematic because of the
  // memory arrangement
  std::cout << "----- casting Derived to Base1 -----" << std::endl;
  std::cout << "pCCastedB1          ->test0() => ";  
  pCCastedD1          ->test0();
  std::cout << "pCCastedB1          ->test1() => ";  
  pCCastedD1          ->test1();
  std::cout << "pStaticcastedB1     ->test0() => ";  
  pStaticcastedD1     ->test0();
  std::cout << "pStaticcastedB1     ->test1() => ";  
  pStaticcastedD1     ->test1();
  std::cout << "pDynamiccastedD1    ->test0() => ";  
  pDynamiccastedD1    ->test0();
  std::cout << "pDynamiccastedD1    ->test1() => ";  
  pDynamiccastedD1    ->test1();

  std::cout << "Next is wrong, most likely output is wrong (test0 outputs test1)\n";
  std::cout << "pReinterpretcastedB1->test0() => ";  
  pReinterpretcastedD1->test0(); // wrong
  std::cout << "Next is wrong, mosy likely crash (Segmentation fault)" << std::endl;
  std::cout << "pReinterpretcastedB1->test1() => ";  
  pReinterpretcastedD1->test1(); // wrong
}
