Sunday, June 13, 2010

static typecasting in C++

The "static_cast" keyword.
  • Operates on references and pointers of class and on the inbuilt data types and class with conversion constructors.
  • In the case of inbuilt data types it converts the value into the new type.
  • In the case of conversion constructor classes, it creates a new object from the original object using the conversion constructor. Note that copy constructors ARE conversion constructors and WILL be implicitly apply to any derived class.
  • In the case of pointers and references:

    • The cast confirms at compile time that the pointers convert from and to are are related by inheritance, ie they share the same Base class a some point.
    • Since the cast performs no RTTI check the it is faster and lighter than the "dynamic_cast".
    • If used badly on pointers or references it can convert invalidly, for example a base class can be converted to a Derived class despite the fact that it wont have memory for the derived classes member variables.

//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
  BaseB()         { }
  BaseB(BaseA& A) { cout << "Converting BaseA" << endl; }
  virtual void print() { cout << "BaseA"; }

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

  cout << "static casting: inbuilt datatypes " << endl;
  char       char1    = static_cast<char>(int1); 
  int        int2     = static_cast<int>(double1); 

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

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

  cout << "static casting: conversion constructor classes " << endl;
  BaseB      objB     = static_cast<BaseB>(*base1);
  BaseA      objA1    = static_cast<BaseA>(*base2); //OK the default copy constructor IS a conversion constructor 
  //BaseA      objA2    = static_cast<BaseA>(*baseB); //BAD no conversion constructor 

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

  //char*      charPtr  = static_cast<char*>(&int1);     //BAD int and char dont share any inhertance.
  //BaseB*     base5    = static_cast<BaseB*>(derived1); //BAD BaseB and dervied1 dont share any inhertance.

  cout << "static casting: references " << endl;
  DerivedA1& refDerived1    = static_cast<DerivedA1&>(*base1); //BAD base1 doesnt have the correct memory to be DerivedA1 class! 
  DerivedA1& refDerived2 = static_cast<DerivedA1&>(*base2);
  DerivedA2& refDerived3 = static_cast<DerivedA2&>(*base2);
  DerivedA1& refDerived4 = static_cast<DerivedA1&>(*base3);
  BaseA& refBase         = static_cast<BaseA&>(*derived1);
  //BaseB& refBaseB        = static_cast<BaseB&>(*derived1); //BAD BaseB and dervied1 dont share any inhertance.

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

No comments:

Post a Comment