Click here to Skip to main content
15,888,454 members
Home / Discussions / C / C++ / MFC
   

C / C++ / MFC

 
QuestionRe: How does this code with "event" functions? Pin
Vaclav_17-Oct-13 8:59
Vaclav_17-Oct-13 8:59 
QuestionDisk Wipe Pin
Member 862075915-Oct-13 23:52
Member 862075915-Oct-13 23:52 
AnswerRe: Disk Wipe Pin
Member 862075916-Oct-13 2:11
Member 862075916-Oct-13 2:11 
AnswerRe: Disk Wipe Pin
Vaclav_16-Oct-13 14:43
Vaclav_16-Oct-13 14:43 
SuggestionRe: Disk Wipe Pin
SoMad16-Oct-13 17:17
professionalSoMad16-Oct-13 17:17 
AnswerRe: Disk Wipe Pin
Albert Holguin17-Oct-13 5:33
professionalAlbert Holguin17-Oct-13 5:33 
AnswerRe: Disk Wipe Pin
TheKingofdemon3318-Oct-13 9:14
TheKingofdemon3318-Oct-13 9:14 
QuestionPolymorphism & Assignment Op. & Copy Constructors in C++ Pin
federico.strati15-Oct-13 2:16
federico.strati15-Oct-13 2:16 
The following question is about how to handle assignment operators (& copy constructors)
in a hierarchy of polymorphic objects in order to be able to work with all kind of assignments & copy:
i.e. we would ideally like to work always with base class pointers, but also allow to use
directly derived class pointers.

In fact I do present two techniques to deal with this argument:

A) The first does make use of "virtual" assignment operators
and, as far as I know, should be the "standard" way to deal with this argument in C++,
but it has the drawback that as soon as your hierarchy is more than one level deep
it leads to a combinatorial explosion of assignment operators.

This technique I call "Polymorphism A" in the following.

B) The second technique does make use of an aux virtual copy method,
using this aux virtual copy method fewer assignment operators have to be defined,
but it has the drawback that you cannot call directly the base class assignment op. from derived ones.

This technique I call "Polymorphism B" in the following.

My question is more like an open discussion: i.e. I do ask what are your opinions on both techniques,
what drawbacks you may see in them, and, eventually, if you do know of a better way to solve the same problem.

In the sample code I give objects are relatively simple, but keep in mind that we would like
to apply those techniques to complicated objects where "deep" copies are to be used.

Let us see the code:
------- Polymorphism A - hierarchy --------------------
C++
// PolymorphismA.cpp

#include "stdafx.h"

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>

using namespace std;

// We want, inasmuch as possible, to work only with CBase pointers
// but we have a hierarchy based on CBase derived classes

class CBase // CBase is our base class
{
private:
   CBase() // default ctor is protected, we do not want to default construct
   { cout << "CBase() default ctor called" << endl; 
     _data = -1; _isvalid = false; };

public:
   explicit CBase(const int data) // explicit Construction
   { cout << "CBase(const int data) explicit ctor called" << endl; 
     _data = data; _isvalid = true; };
   virtual ~CBase() // polymorphism, virtual dtor
   { cout << "~CBase() dtor called" << endl; };

public:
   // CBase and derived objects are copy-constructible and assignable through base pointers
   CBase(const CBase& iOther) // it cannot be declared as virtual
   { cout << "CBase(const CBase& iOther) copy ctor called" << endl; 
     copyBase(iOther); // copy the base
   };
   virtual CBase& operator=(const CBase& iOther) // we declare it as virtual
   { cout << "CBase& CBase::operator=(const CBase& iOther) assignment called" << endl; 
     if( this != &iOther ) // prevents self-assignment
     {
        copyBase(iOther); // copy the base
     }
     return *this;
   };

private:
   // Aux Method to copy the base class, common to copy ctor and assignment op.
   void copyBase(const CBase& iOther)
   { cout << "CBase::copyBase() copy called" << endl; 
     _data = iOther._data; _isvalid = iOther._isvalid; };

public: // we also have real methods
   int getData() const // Accessor
   { return _data; };
   void setData(const int data) // Setter
   { _data = data; };
   bool isValid() const // Accessor
   { return _isvalid; };
   void setValid(const bool isvalid) // Setter
   { _isvalid = isvalid; };

private:
   int _data;     // CBase state
   bool _isvalid; // CBase state
};

class CDerivedA : public CBase // CDerivedA is derived from CBase interface
{
private:
   CDerivedA() // default ctor is protected, we do not want to default construct
      : CBase((int) -1)
   { cout << "CDerivedA() default ctor called" << endl; 
     _dataA = -1.0; setValid(false); };

public:
   explicit CDerivedA(const double dataA) // explicit Construction
      : CBase((int) 0) // explicitly invoke base constructor
   { cout << "CDerivedA(const double dataA) explicit ctor called" << endl; 
     _dataA = dataA; };
   virtual ~CDerivedA() // polymorphism, virtual dtor
   { cout << "~CDerivedA() dtor called" << endl; };

public:
   // Also CDerivedA are copy-constructible and assignable in case we work directly with pointers to CDerivedA
   // We need Specific to this class copy ctor & assignment op.
   CDerivedA(const CDerivedA& iOther) // it cannot be declared as virtual
      : CBase(iOther) // copy the base by calling the base copy ctor
   { cout << "CDerivedA(const CDerivedA& iOther) copy ctor called" << endl; 
     _dataA = iOther._dataA; // our specific data copy
   };
   virtual CDerivedA& operator=(const CDerivedA& iOther) // declared as virtual for further derivation
   { cout << "CDerivedA& CDerivedA::operator=(const CDerivedA& iOther) assignment called" << endl; 
     if( this != &iOther ) // prevents self-assignment
     {
        // We may call the base class assignment operator... as in
        this->CBase::operator=(iOther);
        // ... or we may call the base copy ctor
        // this->CBase::CBase(iOther);
        _dataA = iOther._dataA; // our specific data copy
     }
     return *this;
   };
   // Define a new copy ctor if we are passed the base class pointer
   CDerivedA(const CBase& iOther)
      : CBase(iOther) // copy the base by calling the base copy ctor
   { cout << "CDerivedA(const CBase& iOther) copy ctor called" << endl;
     // our specific data copy
     // here we do the derived class copy, but we have a CBase object to deal with...
     // we need to see if we are of the same kind.
     buildVirtualCopy(iOther);
   };
   // Override the base class assignment operator
   virtual CBase& operator=(const CBase& iOther) // declared as virtual in base class
   { cout << "CBase& CDerivedA::operator=(const CBase& iOther) assignment called" << endl; 
     if( this != &iOther ) // prevents self-assignment
     {
        // We may call the base class assignment operator... as in
        this->CBase::operator=(iOther);
        // ... or we may call the base copy ctor
        // this->CBase::CBase(iOther);
        // our specific data copy
        // here we do the derived class copy, but we have a CBase object to deal with...
        // we need to see if we are of the same kind.
        buildVirtualCopy(iOther);
     }
     return *this;
   };

private:
   // aux method
   void buildVirtualCopy(const CBase& iOther)
   {
      cout << "CDerivedA::buildVirtualCopy copy ctor called" << endl;
      // try to down-cast to our type
      const CDerivedA* pOther = dynamic_cast<const CDerivedA*> (&iOther);
      if ( nullptr != pOther ) // we are of the same kind
      {
         // do the copy
         _dataA = pOther->_dataA;
      } 
      else // deal with different object kind
      {
         cout << "CDerivedA: explicit conversion from other type is forbidden" << endl;
         setValid(false); // here we just set the copy as invalid
         // but we could also have thrown an exception
         // ... or defined an explicit conversion policy from other types
      }
   };

public: // we have also real methods
   double getDataA() const // Accessor
   { return _dataA; };
   void setDataA(const double dataA) // Setter
   { _dataA = dataA; };

private:
   double _dataA; // CDerivedA state
};

class CDerivedB : public CBase // CDerivedB is derived from CBase interface
{
private:
   CDerivedB() // default ctor is protected, we do not want to default construct
      : CBase((int) -1)
   { cout << "CDerivedB() default ctor called" << endl; 
     _dataB = ""; setValid(false); };

public:
   explicit CDerivedB(const string dataB) // explicit Construction
      : CBase((int) 1) // explicitly invoke base constructor
   { cout << "CDerivedB(const string dataB) explicit ctor called" << endl; 
     _dataB = dataB; };
   virtual ~CDerivedB() // polymorphism, virtual dtor
   { cout << "~CDerivedB() dtor called" << endl; };

public:
   // Also CDerivedB are copy-constructible and assignable in case we work directly with pointers to CDerivedB
   // We need Specific to this class copy ctor & assignment op.
   CDerivedB(const CDerivedB& iOther) // it cannot be declared as virtual
      : CBase(iOther) // copy the base by calling the base copy ctor
   { cout << "CDerivedB(const CDerivedB& iOther) copy ctor called" << endl; 
     _dataB = iOther._dataB; // our specific data copy
   };
   virtual CDerivedB& operator=(const CDerivedB& iOther) // declared as virtual for further derivation
   { cout << "CDerivedB& CDerivedB::operator=(const CDerivedB& iOther) assignment called" << endl; 
     if( this != &iOther ) // prevents self-assignment
     {
        // We may call the base class assignment operator... as in
        this->CBase::operator=(iOther);
        // ... or we may call the base copy ctor
        // this->CBase::CBase(iOther);
        _dataB = iOther._dataB; // our specific data copy
     }
     return *this;
   };
   // Define a new copy ctor if we are passed the base class pointer
   CDerivedB(const CBase& iOther)
      : CBase(iOther) // copy the base by calling the base copy ctor
   { cout << "CDerivedB(const CBase& iOther) copy ctor called" << endl;
     // our specific data copy
     // here we do the derived class copy, but we have a CBase object to deal with...
     // we need to see if we are of the same kind.
     buildVirtualCopy(iOther);
   };
   // Override the base class assignment operator
   virtual CBase& operator=(const CBase& iOther) // declared as virtual in base class
   { cout << "CBase& CDerivedB::operator=(const CBase& iOther) assignment called" << endl; 
     if( this != &iOther ) // prevents self-assignment
     {
        // We may call the base class assignment operator... as in
        this->CBase::operator=(iOther);
        // ... or we may call the base copy ctor
        // this->CBase::CBase(iOther);

        // our specific data copy
        // here we do the derived class copy, but we have a CBase object to deal with...
        // we need to see if we are of the same kind.
        buildVirtualCopy(iOther);
     }
     return *this;
   };

private:
   // aux method
   void buildVirtualCopy(const CBase& iOther)
   {
      cout << "CDerivedB::buildVirtualCopy copy ctor called" << endl;
      // try to down-cast to our type
      const CDerivedB* pOther = dynamic_cast<const CDerivedB*> (&iOther); 
      if ( nullptr != pOther ) // we are of the same kind
      {
         // do the copy
         _dataB = pOther->_dataB;
      } 
      else // deal with different object kind
      {
         // let us look for a type we know of (cross-cast)
         // try to down-cast to this other type
         const CDerivedA* pOtherA = dynamic_cast<const CDerivedA*> (&iOther); 
         if ( nullptr != pOtherA ) // we know about this type
         {
            // do a conversion copy
            stringstream ss;
            ss << setw(4) << pOtherA->getDataA();
            _dataB = ss.str();
            cout << "CDerivedB: explicit conversion from CDerivedA type" << endl;
         } 
         else // deal with different object kind
         {
            setValid(false); // here we just set the copy as invalid
            // but we could also have thrown an exception
         }
      }
   };

public: // we have also real methods
   string getDataB() const // Accessor
   { return _dataB; };
   void setDataB(const string& dataB) // Setter
   { _dataB = dataB; };

private:
   string _dataB; // CDerivedB state
};

------- Polymorphism A - hierarchy --------------------

------- Polymorphism B - hierarchy --------------------
C++
// PolymorphismB.cpp

#include "stdafx.h"

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>

using namespace std;

// We want, inasmuch as possible, to work only with CBase pointers
// but we have a hierarchy based on CBase derived classes

class CBase // CBase is our base class
{
private:
   CBase() // default ctor is protected, we do not want to default construct
   { cout << "CBase() default ctor called" << endl; 
     _data = -1; _isvalid = false; };

public:
   explicit CBase(const int data) // explicit Construction
   { cout << "CBase(const int data) explicit ctor called" << endl; 
     _data = data; _isvalid = true; };
   virtual ~CBase() // polymorphism, virtual dtor
   { cout << "~CBase() dtor called" << endl; };

public:
   // CBase and derived objects are copy-constructible and assignable through base pointers
   CBase(const CBase& iOther) // it cannot be declared as virtual
   { cout << "CBase(const CBase& iOther) copy ctor called" << endl; 
     copyBase(iOther); // copy the base
     // it does not know about other types, No need to call virtual copy
   };
   CBase& operator=(const CBase& iOther) // invoking virtual copy method
   { cout << "CBase& CBase::operator=(const CBase& iOther) assignment called" << endl; 
     if( this != &iOther ) // prevents self-assignment
     {
        copyBase(iOther); // copy the base
        buildVirtualCopy(iOther); // Delegate to virtual copy if needed
     }
     return *this;
   };

private:
   // Aux Method to copy the base class
   void copyBase(const CBase& iOther)
   { cout << "CBase::copyBase() copy called" << endl; 
     _data = iOther._data; _isvalid = iOther._isvalid; };

protected:
   // Aux Method for derived classes copy
   virtual void buildVirtualCopy(const CBase& iOther) // do nothing in base class
   { cout << "CBase::buildVirtualCopy copy ctor called, it does nothing" << endl; };

public: // we also have real methods
   int getData() const // Accessor
   { return _data; };
   void setData(const int data) // Setter
   { _data = data; };
   bool isValid() const // Accessor
   { return _isvalid; };
   void setValid(const bool isvalid) // Setter
   { _isvalid = isvalid; };

private:
   int _data;     // CBase state
   bool _isvalid; // CBase state
};

class CDerivedA : public CBase // CDerivedA is derived from CBase interface
{
private:
   CDerivedA() // default ctor is protected, we do not want to default construct
      : CBase((int) -1)
   { cout << "CDerivedA() default ctor called" << endl; 
     _dataA = -1.0; setValid(false); };

public:
   explicit CDerivedA(const double dataA) // explicit Construction
      : CBase((int) 0) // explicitly invoke base constructor
   { cout << "CDerivedA(const double dataA) explicit ctor called" << endl; 
     _dataA = dataA; };
   virtual ~CDerivedA() // polymorphism, virtual dtor
   { cout << "~CDerivedA() dtor called" << endl; };

public:
   // Also CDerivedA are copy-constructible and assignable in case we work directly with pointers to CDerivedA
   // We need Specific to this class copy ctor & assignment op.
   CDerivedA(const CDerivedA& iOther) // it cannot be declared as virtual
      : CBase(iOther) // copy the base by calling the base copy ctor
   { cout << "CDerivedA(const CDerivedA& iOther) copy ctor called" << endl; 
     _dataA = iOther._dataA; // our specific data copy
   };
   CDerivedA& operator=(const CDerivedA& iOther)
   { cout << "CDerivedA& CDerivedA::operator=(const CDerivedA& iOther) assignment called" << endl; 
     if( this != &iOther ) // prevents self-assignment
     {
        // if we call the base class assignment operator... as in
        // this->CBase::operator=(iOther);
        // then we will invoke as well our virtual copy...
        // hence we cannot call the base class assignment operator.
        // but we can do this...
        this->CBase::CBase(iOther); // call the base copy ctor
        _dataA = iOther._dataA; // our specific data copy
     }
     return *this;
   };
   // Define a new copy ctor for the base class pointers
   CDerivedA(const CBase& iOther)
      : CBase(iOther) // copy the base by calling the base copy ctor
   { cout << "CDerivedA(const CBase& iOther) copy ctor called" << endl; 
     // here we do the derived class copy, but we have a CBase object to deal with...
     // we need to see if we are of the same kind.
     buildVirtualCopy(iOther);
   };

protected:
   // aux method
   virtual void buildVirtualCopy(const CBase& iOther)
   {
      cout << "CDerivedA::buildVirtualCopy copy ctor called" << endl;
      // try to down-cast to our type
      const CDerivedA* pOther = dynamic_cast<const CDerivedA*> (&iOther); 
      if ( nullptr != pOther ) // we are of the same kind
      {
         // do the copy
         _dataA = pOther->_dataA;
      } 
      else // deal with different object kind
      {
         cout << "CDerivedA: explicit conversion from other type is forbidden" << endl;
         setValid(false); // here we just set the copy as invalid
         // but we could also have thrown an exception
         // ... or defined an explicit conversion policy from other types
      }
   };

public: // we have also real methods
   double getDataA() const // Accessor
   { return _dataA; };
   void setDataA(const double dataA) // Setter
   { _dataA = dataA; };

private:
   double _dataA; // CDerivedA state
};

class CDerivedB : public CBase // CDerivedB is derived from CBase interface
{
private:
   CDerivedB() // default ctor is protected, we do not want to default construct
      : CBase((int) -1)
   { cout << "CDerivedB() default ctor called" << endl; 
     _dataB = ""; setValid(false); };

public:
   explicit CDerivedB(const string dataB) // explicit Construction
      : CBase((int) 1) // explicitly invoke base constructor
   { cout << "CDerivedB(const string dataB) explicit ctor called" << endl; 
     _dataB = dataB; };
   virtual ~CDerivedB() // polymorphism, virtual dtor
   { cout << "~CDerivedB() dtor called" << endl; };

public:
   // Also CDerivedB are copy-constructible and assignable in case we work directly with pointers to CDerivedB
   // We need Specific to this class copy ctor & assignment op.
   CDerivedB(const CDerivedB& iOther) // it cannot be declared as virtual
      : CBase(iOther) // copy the base by calling the base copy ctor
   { cout << "CDerivedB(const CDerivedB& iOther) copy ctor called" << endl; 
     _dataB = iOther._dataB; // our specific data copy
   };
   CDerivedB& operator=(const CDerivedB& iOther)
   { cout << "CDerivedB& CDerivedB::operator=(const CDerivedB& iOther) assignment called" << endl; 
     if( this != &iOther ) // prevents self-assignment
     {
        // if we call the base class assignment operator... as in
        // this->CBase::operator=(iOther);
        // then we will invoke as well our virtual copy...
        // hence we cannot call the base class assignment operator.
        // but we can do this...
        this->CBase::CBase(iOther); // call the base copy ctor
        _dataB = iOther._dataB; // our specific data copy
     }
     return *this;
   };
   // Override the base class copy ctor & assignment op.
   CDerivedB(const CBase& iOther) // it cannot be declared as virtual
      : CBase(iOther) // copy the base by calling the base copy ctor
   { cout << "CDerivedB(const CBase& iOther) copy ctor called" << endl; 
     // copyBase(iOther); // we cannot use directly this base method, otherwise default ctor invoked
     // here we do the derived class copy, but we have a CBase object to deal with...
     // we need to see if we are of the same kind.
     buildVirtualCopy(iOther);
   };

protected:
   // aux method
   virtual void buildVirtualCopy(const CBase& iOther)
   {
      cout << "CDerivedB::buildVirtualCopy copy ctor called" << endl;
      // try to down-cast to our type
      const CDerivedB* pOther = dynamic_cast<const CDerivedB*> (&iOther); 
      if ( nullptr != pOther ) // we are of the same kind
      {
         // do the copy
         _dataB = pOther->_dataB;
      } 
      else // deal with different object kind
      {
         // let us look for a type we know of (cross-cast)
         // try to down-cast to this other type
         const CDerivedA* pOtherA = dynamic_cast<const CDerivedA*> (&iOther); 
         if ( nullptr != pOtherA ) // we know about this type
         {
            // do a conversion copy
            stringstream ss;
            ss << setw(4) << pOtherA->getDataA();
            _dataB = ss.str();
            cout << "CDerivedB: explicit conversion from CDerivedA type" << endl;
         } 
         else // deal with different object kind
         {
            setValid(false); // here we just set the copy as invalid
            // but we could also have thrown an exception
         }
      }
   };

public: // we have also real methods
   string getDataB() const // Accessor
   { return _dataB; };
   void setDataB(const string& dataB) // Setter
   { _dataB = dataB; };

private:
   string _dataB; // CDerivedB state
};

------- Polymorphism B - hierarchy --------------------

and a simple test program to test both of them:

------- test program for both hierarchies -------------
C++
// Now let us play with our types
int _tmain(int argc, _TCHAR* argv[])
{
   cout << "Program starts..." << endl;
   cout << endl;

   {
      CDerivedA* pA0 = new CDerivedA((double) 1.0);
      CDerivedA* pA1 = new CDerivedA((double) 2.0);
      CDerivedB* pB0 = new CDerivedB(string("This is B1"));
      CDerivedB* pB1 = new CDerivedB(string("This is B2"));
      cout << endl;

      CBase* p00 = nullptr;
      CBase* p01 = nullptr;

      // Assignment via base pointers of type A objects
      cout << "Assignment via base pointers of type A objects" << endl;
      p00 = pA0;
      p01 = pA1;
      // A0 <-- A1
      *p00 = *p01;
      cout << "pA0 dataA = " << pA0->getDataA() << endl;
      cout << "pA1 dataA = " << pA1->getDataA() << endl;
      cout << endl;

      p00 = nullptr;
      p01 = nullptr;

      // Assignment via base pointers of type B objects
      cout << "Assignment via base pointers of type B objects" << endl;
      p00 = pB0;
      p01 = pB1;
      // B0 <-- B1
      *p00 = *p01;
      cout << "pB0 dataB = " << pB0->getDataB() << endl;
      cout << "pB1 dataB = " << pB1->getDataB() << endl;
      cout << endl;

      p00 = nullptr;
      p01 = nullptr;

      // "cross assignment": from B type to A type is forbidden
      cout << "Cross Assignment via base pointers from type B objects to type A is forbidden" << endl;
      p00 = pA0;
      p01 = pB0;
      // A0 <-- B0, forbidden
      cout << "p00 is pointing to pA0 " << endl;
      *p00 = *p01;
      cout << "p00 is valid = " << p00->isValid() << endl;
      cout << endl;

      p00 = nullptr;
      p01 = nullptr;

      // "cross assignment": from A type to B type is allowed
      cout << "Cross Assignment via base pointers from type A objects to type B" << endl;
      cout << "is allowed by custom conversion... " << endl;
      p00 = pB1;
      p01 = pA1;
      // B1 <-- A1, custom conversion allowed
      cout << "p00 is pointing to pB1 " << endl;
      *p00 = *p01;
      cout << "p00 is valid = " << p00->isValid() << endl;
      cout << "p00 --> pB1 dataB = " << pB1->getDataB() << endl;
      cout << endl;

      p00 = nullptr;
      p01 = nullptr;

      delete pA0;
      delete pA1;
      delete pB0;
      delete pB1;
      cout << endl;
   }

   // we can deal directly with pointers to derived classes
   {
      CDerivedA* pA0 = new CDerivedA((double) 1.0);
      CDerivedA* pA1 = new CDerivedA((double) 2.0);
      CDerivedB* pB0 = new CDerivedB(string("This is B1"));
      CDerivedB* pB1 = new CDerivedB(string("This is B2"));
      cout << endl;

      // Assignment via pointers of type A objects
      cout << "Assignment via pointers of type A objects" << endl;
      // A0 <-- A1
      *pA0 = *pA1;
      cout << "pA0 dataA = " << pA0->getDataA() << endl;
      cout << "pA1 dataA = " << pA1->getDataA() << endl;
      cout << endl;

      // Assignment via pointers of type B objects
      cout << "Assignment via pointers of type B objects" << endl;
      // B0 <-- B1
      *pB0 = *pB1;
      cout << "pB0 dataB = " << pB0->getDataB() << endl;
      cout << "pB1 dataB = " << pB1->getDataB() << endl;
      cout << endl;

      delete pA0;
      delete pA1;
      delete pB0;
      delete pB1;
      cout << endl;
   }

   // of course we can deal also with base classes
   {
      cout << "Base class Assignment just works." << endl;
      CBase* p00 = nullptr;
      CBase* p01 = nullptr;
      p00 = new CBase((int) 10);
      p01 = new CBase((int) 11);
      *p00 = *p01;
      cout << "p00 is valid = " << p00->isValid() << endl;
      cout << "p00 data = " << p00->getData() << endl;
      cout << "p01 is valid = " << p01->isValid() << endl;
      cout << "p01 data = " << p01->getData() << endl;
      cout << endl;

      delete p00;
      cout << endl;

      cout << "Base class copy ctor just works." << endl;
      p00 = new CBase(*p01);
      cout << "p00 is valid = " << p00->isValid() << endl;
      cout << "p00 data = " << p00->getData() << endl;

      delete p00;
      delete p01;
      cout << endl;
   }

   // what about copy construction ?
   {
      // Copy ctor via pointers of type A objects
      cout << "Copy ctor via pointers of type A objects" << endl;
      CDerivedA* pA1 = new CDerivedA((double) 2.0);
      cout << endl;
      CDerivedA* pA2 = new CDerivedA(*pA1);
      cout << "pA1 dataA = " << pA1->getDataA() << endl;
      cout << "pA2 dataA = " << pA2->getDataA() << endl;
      delete pA1;
      delete pA2;
      cout << endl;

      // Copy ctor via pointers of type B objects
      cout << "Copy ctor via pointers of type B objects" << endl;
      CDerivedB* pB1 = new CDerivedB(string("This is B2"));
      cout << endl;
      CDerivedB* pB2 = new CDerivedB(*pB1);
      cout << "pB1 dataB = " << pB1->getDataB() << endl;
      cout << "pB2 dataB = " << pB2->getDataB() << endl;
      delete pB1;
      delete pB2;
      cout << endl;

      // Copy ctor via base pointers of type A,B objects
      cout << "Copy ctor via base pointers of type A,B objects" << endl;
      CBase* p00 = new CDerivedA((double) 1.0);
      CBase* p01 = new CDerivedB(string("This is B1"));
      cout << endl;

      cout << "A from A via base" << endl;
      CDerivedA* pA3 = new CDerivedA(*p00);
      cout << endl;
      cout << "base from A (slicing)" << endl;
      CBase*     pA4 = new CBase(*p00); // slice it
      cout << endl;

      cout << "B from B via base" << endl;
      CDerivedB* pB3 = new CDerivedB(*p01);
      cout << endl;
      cout << "base from B (slicing)" << endl;
      CBase*     pB4 = new CBase(*p01); // slice it
      cout << endl;

      cout << "A from B via base" << endl;
      CDerivedA* pA5 = new CDerivedA(*p01);
      cout << endl;

      cout << "B from A via base" << endl;
      CDerivedB* pB5 = new CDerivedB(*p00);
      cout << endl;

      delete pA3;
      delete pA4;
      delete pA5;

      delete pB3;
      delete pB4;
      delete pB5;

      delete p00;
      delete p01;

      cout << endl;
   }

   int k = getchar();
   return 0;
}

------- test program for both hierarchies -------------

Thanks in advance for any suggestion about why you would go with one instead of the other
(or, if eventually you do know a better idiomatic solution).

Federico
AnswerRe: Polymorphism & Assignment Op. & Copy Constructors in C++ Pin
Aescleal21-Oct-13 4:45
Aescleal21-Oct-13 4:45 
GeneralRe: Polymorphism & Assignment Op. & Copy Constructors in C++ Pin
federico.strati21-Oct-13 22:04
federico.strati21-Oct-13 22:04 
GeneralRe: Polymorphism & Assignment Op. & Copy Constructors in C++ Pin
Aescleal21-Oct-13 23:15
Aescleal21-Oct-13 23:15 
GeneralRe: Polymorphism & Assignment Op. & Copy Constructors in C++ Pin
federico.strati22-Oct-13 0:12
federico.strati22-Oct-13 0:12 
QuestionSQLFetchScroll is failing if database column contains NULL value Pin
Ashish Ranjan Mishra14-Oct-13 21:13
Ashish Ranjan Mishra14-Oct-13 21:13 
AnswerRe: SQLFetchScroll is failing if database column contains NULL value Pin
Rajesh R Subramanian14-Oct-13 22:24
professionalRajesh R Subramanian14-Oct-13 22:24 
GeneralRe: SQLFetchScroll is failing if database column contains NULL value Pin
Ashish Ranjan Mishra14-Oct-13 23:24
Ashish Ranjan Mishra14-Oct-13 23:24 
GeneralRe: SQLFetchScroll is failing if database column contains NULL value Pin
Rajesh R Subramanian14-Oct-13 23:29
professionalRajesh R Subramanian14-Oct-13 23:29 
GeneralRe: SQLFetchScroll is failing if database column contains NULL value Pin
Rajesh R Subramanian14-Oct-13 23:34
professionalRajesh R Subramanian14-Oct-13 23:34 
GeneralRe: SQLFetchScroll is failing if database column contains NULL value Pin
Ashish Ranjan Mishra15-Oct-13 9:41
Ashish Ranjan Mishra15-Oct-13 9:41 
GeneralRe: SQLFetchScroll is failing if database column contains NULL value Pin
Rajesh R Subramanian15-Oct-13 11:30
professionalRajesh R Subramanian15-Oct-13 11:30 
QuestionPassing class pointer via socket Pin
Don Guy14-Oct-13 13:09
Don Guy14-Oct-13 13:09 
AnswerRe: Passing class pointer via socket Pin
Richard Andrew x6414-Oct-13 14:34
professionalRichard Andrew x6414-Oct-13 14:34 
GeneralRe: Passing class pointer via socket Pin
pasztorpisti14-Oct-13 21:50
pasztorpisti14-Oct-13 21:50 
AnswerRe: Passing class pointer via socket Pin
Erudite_Eric14-Oct-13 17:10
Erudite_Eric14-Oct-13 17:10 
AnswerRe: Passing class pointer via socket Pin
ExcellentOrg14-Oct-13 21:20
ExcellentOrg14-Oct-13 21:20 
AnswerRe: Passing class pointer via socket Pin
Rajesh R Subramanian14-Oct-13 22:43
professionalRajesh R Subramanian14-Oct-13 22:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.