pghsteelers
Technical User
I was hoping someone could explain the following issue regarding the need to call a copy constructor for the base part of the class in the initialization list for the copy constructor for the derived class (NOTE: complete code at bottom)- as pointed out as:
- A problem when initializing a new object by copying from an existing object
(i.e. classname newobject2(newobject1) )
- when writing a constructor for an object of a derived class, you are responsible for ensuring that the members of the derived class object are properly intialized - including inherited members.
(example:
//derived class copy constructor
CSample(const CSample& initCS): CBase(initCS)
My issue is that I don't quite understand "Why" if you don't do this, calling a copy constructor from the base in a derived class ends up just calling the constructor and not the copy constructor. See Code below for example:
#include <iostream> // For stream I/O
#include <cstring> // For strlen() and strcpy()
using namespace std;
// Listing 10_05-01
class CBox // Base class definition
{
public:
// Base class constructor
CBox(double lv = 1.0, double bv = 1.0, double hv = 1.0):
m_Length(lv), m_Breadth(bv), m_Height(hv)
{ cout << endl << "CBox constructor called"; }
// Copy constructor
CBox(const CBox& initB)
{
cout << endl << "CBox copy constructor called";
m_Length = initB.m_Length;
m_Breadth = initB.m_Breadth;
m_Height = initB.m_Height;
}
// CBox destructor - just to track calls
~CBox()
{ cout << "CBox destructor called" << endl; }
protected:
double m_Length;
double m_Breadth;
double m_Height;
};
// Listing 10_05-02
class CCandyBox: public CBox
{
public:
char* m_Contents;
// Derived class function to calculate volume
double Volume() const
{ return m_Length*m_Breadth*m_Height; }
// Constructor to set dimensions and contents
// with explicit call of CBox constructor
CCandyBox(double lv, double bv, double hv, char* str = "Candy")
:CBox(lv, bv, hv) // Constructor
{
cout << endl <<"CCandyBox constructor2 called";
m_Contents = new char[ strlen(str) + 1 ];
strcpy(m_Contents, str);
}
// Constructor to set contents
// calls default CBox constructor automatically
CCandyBox(char* str = "Candy") // Constructor
{
cout << endl << "CCandyBox constructor1 called";
m_Contents = new char[ strlen(str) + 1 ];
strcpy(m_Contents, str);
}
~CCandyBox() // Destructor
{
cout << "CCandyBox destructor called" << endl;
delete[] m_Contents;
}
};
int main()
{
CCandyBox chocBox(2.0, 3.0, 4.0, "Chockies"); // Declare and initialize
CCandyBox chocolateBox(chocBox); // Use copy constructor
cout << endl
<< "Volume of chocBox is " << chocBox.Volume()
<< endl
<< "Volume of chocolateBox is " << chocolateBox.Volume()
<< endl;
return 0;
}
The problem exist when the newobject2 gets the default constructor values rather than the values of the object it was trying to copy from. Stating that you have to
- A problem when initializing a new object by copying from an existing object
(i.e. classname newobject2(newobject1) )
- when writing a constructor for an object of a derived class, you are responsible for ensuring that the members of the derived class object are properly intialized - including inherited members.
(example:
//derived class copy constructor
CSample(const CSample& initCS): CBase(initCS)
My issue is that I don't quite understand "Why" if you don't do this, calling a copy constructor from the base in a derived class ends up just calling the constructor and not the copy constructor. See Code below for example:
#include <iostream> // For stream I/O
#include <cstring> // For strlen() and strcpy()
using namespace std;
// Listing 10_05-01
class CBox // Base class definition
{
public:
// Base class constructor
CBox(double lv = 1.0, double bv = 1.0, double hv = 1.0):
m_Length(lv), m_Breadth(bv), m_Height(hv)
{ cout << endl << "CBox constructor called"; }
// Copy constructor
CBox(const CBox& initB)
{
cout << endl << "CBox copy constructor called";
m_Length = initB.m_Length;
m_Breadth = initB.m_Breadth;
m_Height = initB.m_Height;
}
// CBox destructor - just to track calls
~CBox()
{ cout << "CBox destructor called" << endl; }
protected:
double m_Length;
double m_Breadth;
double m_Height;
};
// Listing 10_05-02
class CCandyBox: public CBox
{
public:
char* m_Contents;
// Derived class function to calculate volume
double Volume() const
{ return m_Length*m_Breadth*m_Height; }
// Constructor to set dimensions and contents
// with explicit call of CBox constructor
CCandyBox(double lv, double bv, double hv, char* str = "Candy")
:CBox(lv, bv, hv) // Constructor
{
cout << endl <<"CCandyBox constructor2 called";
m_Contents = new char[ strlen(str) + 1 ];
strcpy(m_Contents, str);
}
// Constructor to set contents
// calls default CBox constructor automatically
CCandyBox(char* str = "Candy") // Constructor
{
cout << endl << "CCandyBox constructor1 called";
m_Contents = new char[ strlen(str) + 1 ];
strcpy(m_Contents, str);
}
~CCandyBox() // Destructor
{
cout << "CCandyBox destructor called" << endl;
delete[] m_Contents;
}
};
int main()
{
CCandyBox chocBox(2.0, 3.0, 4.0, "Chockies"); // Declare and initialize
CCandyBox chocolateBox(chocBox); // Use copy constructor
cout << endl
<< "Volume of chocBox is " << chocBox.Volume()
<< endl
<< "Volume of chocolateBox is " << chocolateBox.Volume()
<< endl;
return 0;
}
The problem exist when the newobject2 gets the default constructor values rather than the values of the object it was trying to copy from. Stating that you have to