Saturday, June 12, 2010

dynamic typecasting in C++

The "dynamic_cast" keyword.
  • Operates on references and pointers only.
  • Requires the item be a class and that class to be a polymorphic class, ie it has at least one virtual function
  • Uses the RTTI information to check the capability of the conversion at runtime
  • In the case of references it will throw an exception if the conversion failed.
  • In the case of pointers it will return NULL if the conversion failed.

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

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

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

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

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

int main()
{
  int int1 = 100;
  BaseA*     base1 = new BaseA();

  //derived class dont need casting into the base
  BaseA*     base2    = new DerivedA2();
  BaseA*     base3    = new DerivedA3();
  DerivedA3* derived1 = new DerivedA3();

  cout << "dynamic casting: pointers " << endl;
  //char*      char1    = dynamic_cast<char*>(&int1); //BAD requires a class
  DerivedA1* derived2 = dynamic_cast<DerivedA1*>(base2);
  DerivedA2* derived3 = dynamic_cast<DerivedA2*>(base2);
  DerivedA1* derived4 = dynamic_cast<DerivedA1*>(base3);
  BaseA*     base4    = dynamic_cast<BaseA*>(derived1); //OK but overkill
  
  cout << "dynamic_cast<DerivedA1*>(base2); " << (derived2 ? "PASSED" : "FAILED") << endl;
  cout << "dynamic_cast<DerivedA2*>(base2); " << (derived3 ? "PASSED" : "FAILED") << endl;
  cout << "dynamic_cast<DerivedA1*>(base3); " << (derived4 ? "PASSED" : "FAILED") << endl;
  cout << "dynamic_cast<BaseA*>(derived1);  " << (base4 ? "PASSED" : "FAILED") << endl;
  cout << endl;

  cout << "dynamic casting: references " << endl;
  cout << "dynamic_cast<DerivedA1&>(*base2) ";
  try
    { 
      DerivedA1& refDerived = dynamic_cast<DerivedA1&>(*base2); 
      cout << "PASSED" << endl; 
    }
  catch (...)
    { cout << "FAILED" << endl;  }
    
  cout << "dynamic_cast<DerivedA2&>(*base2) ";
  try
    {
      DerivedA2& ptrDerived = dynamic_cast<DerivedA2&>(*base2); 
      cout << "PASSED" << endl;
    }
  catch (...)
    { cout << "FAILED" << endl;  }

  cout << "dynamic_cast<DerivedA1&>(*base3) ";
  try
    { 
      DerivedA1& refDerived = dynamic_cast<DerivedA1&>(*base3); 
      cout << "PASSED" << endl; 
    }
  catch (...)
    { cout << "FAILED" << endl;  }

  cout << "dynamic_cast<BaseA&>(*derived1)  ";
  try
    { 
      BaseA& refBase = dynamic_cast<BaseA&>(*derived1); 
      cout << "PASSED" << endl; 
    }
  catch (...)
    { cout << "FAILED" << endl;  }

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

No comments:

Post a Comment