// ==========================================================================
// $Id: pointer.cpp,v 1.2 2014/11/29 00:31:44 jlang Exp $
// CSI2372 example Code for lecture 13
// ==========================================================================
// (C)opyright:
//
//   Jochen Lang
//   SITE, University of Ottawa
//   800 King Edward Ave.
//   Ottawa, On., K1N 6N5
//   Canada. 
//   http://www.site.uottawa.ca
// 
// Creator: jlang (Jochen Lang)
// Email:   jlang@site.uottawa.ca
// ==========================================================================
// $Log: pointer.cpp,v $
// Revision 1.2  2014/11/29 00:31:44  jlang
// Check-in of in-class version
//
// Revision 1.1  2006/11/19 22:53:31  jlang
// Smart pointer example with ref-count
//
//
// ==========================================================================
#include <iostream>
#include "smart_pointer.h" 


using std::endl;
using std::cout;

class A {
  int d_a;
public:
  A( int _a = 0) : d_a(_a) {
    cout << "A()" << endl;
  }
  virtual ~A() {
    cout << "~A()" << endl;
  }
  void print() {
    cout << "A" << endl;
  }
};

class B : public A {
public:
  B() : A() {
    cout << "B()" << endl;
  }
  ~B() {
    cout << "~B()" << endl;
  }
  void print() {
    cout << "B" << endl;
  }
};



int main() {
  B* bPtr = new B();
  A* aPtr = bPtr;
 
  SmartPtr<A> aSmartPtr( aPtr );

  // Access method through smart pointer
  aSmartPtr->print();
  // Get pointer back again
  aPtr = aSmartPtr.GetImpl();
  // it is still a B
  dynamic_cast<B*>(aPtr)->print();
  
  // Compare pointer equivalence with non-smart pointer
  if ( aPtr == aSmartPtr ) {
    cout << "aPtr == aSmartPtr" << endl;
  }
  if ( aSmartPtr == aPtr) {
    cout << "aSmartPtr == aPtr" << endl;
  }
  // Compare pointer equivalence with parent class
  if ( aSmartPtr == bPtr) {
    cout << "aSmartPtr == bPtr" << endl;
  }
  // Make 10 "copies"
  SmartPtr<A>* sPtrArray[10]; 
  for ( int i=0; i<10; ++i ) {
    sPtrArray[i] = new SmartPtr<A>(aSmartPtr);
  }
  // The pointers point all to the same object
  for ( int i=0; i<10; ++i ) {
    if ( aSmartPtr == *sPtrArray[i] && 
	 *sPtrArray[i] == aPtr ) {
      cout << "aSmartPtr == *sPtrArray[" << i << "]" << endl;
    }
  }
  // delete the 10 copies 
  for ( int i=0; i<10; ++i ) {
    cout << i << ": ";
    delete sPtrArray[i];
  }
  cout << endl;
  // A object still exist since we have one live reference
  aSmartPtr->print();
  return 0;
}
