The rule of thumb in writing classes is that if you need one of these member functions, you need all three.
int i = 0;
In terms of the word classes we have been defining, this is analogous to both of the following:
#include "DynamicWord.h"
void main()
{
DynamicWord a; // no copy constructor needed
DynamicWord b(a); // need a copy constructor to copy a into b
DynamicWord b = a; // this is converted into DynamicWord b(a) so
// also needs a copy constructor
}
If a copy constructor is not specifically defined for a class, the C++ compiler synthesizes one that simply does a bitwise copy: in the example above, each bit of a is copied into b. This is fine for classes in which all the data is statically allocated, but not for dynamic memory allocations, since what is copied is the address to the dynamic memory, no new memory is allocated to make a true copy of the data. Thus, whenever dynamic memory is used, a copy constructor should be explicitly defined.
Fortunately in our case, the constructor is quite easy and we can copy from the Assign function we already have written:
In the DynamicWord.h file we need to add (as a public function)
DynamicWord(DynamicWord);
In the DynamicWord.C file we need to add
DynamicWord::DynamicWord(DynamicWord wordin)
{
word = new char [wordin.maxlength]; // get same amount as wordin had
memset(word, '\0', wordin.maxlength);
maxlength = wordin.maxlength;
// Now, copy:
strcpy(word, wordin.word);
length = wordin.length;
}
(In the above example we can't simply call Assign from the constructor because Assign calls delete on word but we have not allocated any space.)
DynamicWord word1("Gary");
How is wordin passed to the constructor? It must be copied, i.e. a copy constructor is used to pass it in.
Rather than force the compiler to completely copy an object, the const type modifier tells it to simply pass the reference to the object, but treat it as a constant so that the passed-in object cannot be modified.
The modified code is as follows:
In the DynamicWord.h file we need to add (as a public function)
DynamicWord(const DynamicWord &);
In the DynamicWord.C file we need to add
DynamicWord::DynamicWord(const DynamicWord & wordin)
{
word = new char [wordin.maxlength]; // get same amount as wordin had
memset(word, '\0', wordin.maxlength);
maxlength = wordin.maxlength;
// Now, copy:
strcpy(word, wordin.word);
length = wordin.length;
}
DynamicWord a; DynamicWord b; b = a;
Like the copy constructor, this is disastrous in the case of a class using dynamic memory since only the pointer to the data is copied. Thus, you should generally overload this operator yourself.
In the case of our DynamicWord, the Assign function does nearly everything we want. There are two differences between it and the operator= function. First, the name, which is easy to modify by operator overloading. The second difference is that operator= returns a reference to the object to which it just assigned a value. If we overload, we should also do this.
Thus, our overloaded prototype for operator= on a DynamicWord looks
like:
DynamicWord & operator= (const DynamicWord &);
The definition of the function looks nearly identical to the Assign function:
DynamicWord & DynamicWord::operator= (const DynamicWord & w)
{ // place contents of w into this word
// First, allocate the space
delete [] word; // get rid of our old allocation
word = new char [w.maxlength]; // get same amount as w had
memset(word, '\0', w.maxlength);
maxlength = w.maxlength;
// Now, copy:
strcpy(word, w.word);
length = w.length;
// Here's the new trick:
return *this;
}
Our new trick for the assignment operator is to return a reference to the object itself. Every class is automatically provided a variable called this which is a pointer to the object. By returning *this we are returning the dereference of the pointer, which is the object itself.
I won't duplicate the destructor code we already wrote, but I will note that, again according to the C++ FAQ authors, generally one notices first that they need an explicit destructor, and then notices the need for the other two functions.