Copy Constructors, Assignment Operators,
Destructors and File IO
The following files are used in this lab:
- date2.h - Declaration for the Date class
- date2.cc - Definition/Implementation for Date class
- testDateCopy.cc - A example program using the copy
constructor and assignment with the Date class.
- snode.h - Declaration file for the SimNode class
- snode.cc - Definition/Implementation for the SimNode class
- olist.h - Declaration for the OrderedList class
- olist.cc - Definition for the OrderedList class
- testListCopy.cc - Example program
illustrating problems with default copy constructor and assignment on
linked lists. Also shows when destructor is called.
- FileIO.cc - Example program illustrating
file IO
C++ provides default destructors, copy constructors, and assignment operators
for objects. These work fine for classes that do not use pointers. However,
classes with pointers and dynamically allocated memory should define versions
of these to correctly allocate and deallocate memory. All three should be
provided.
Copy Constructors
C++ provides a default copy constructor that is invoked with either
of the following object declarations:
ClassName objectName(objectToCopy);
ClassName objectName = objectToCopy;
Either of these declarations sets up the object and copies each data
member of the objectToCopy to the corresponding data
member of the new object.
Warning For data members that are pointers the pointer is
copied but NOT the actual data so the two pointers are now aliases
for the same place in memory. This is called a shallow copy
and causes huge problems!
Assignment Operator
C++ provides a default assignment operator for objects that copies
each data member of the object. For example, the code
object1 = object2;
will copy each data member of object2 into the corresponding
data member of object1. As for the copy constructor, if the
data member is a pointer only the pointer is copied.
Destructors
The destructor for a class is automatically called when an object goes
out of scope. If there is no destructor provided for the class the
default destructor is called; otherwise, the one provided in the class
is called. The destructor should be responsible for freeing all memory
used by an object.
Syntax for the declaration: ~ClassName()
If the class contains a linked list the default destructor frees only the
pointer to the beginning of the list. The programmer should write
code to delete all nodes from the list.
Exercises
- Compile and run testDateCopy.cc and study the code.
No copy constructor
or assignment operator has been defined for the Date class so
the program is using the defaults provided by C++.
- Note that the code behaves as expected.
- Now compile and run testListCopy.cc and study the code.
The copy constructor and the overloaded assignment operator have
been commented out of the OrderedList class. The destructor
code only has a message that the destructor has been called.
Study the output and answer the following (*** WRITE ANSWERS TO
THESE QUESTIONS ***:
- newList1 is a copy of list. What happens when the first
element of list is removed? Why? (Describe in terms of pointers
and links - draw a picture!)
- The node is inserted back in the original list (but not at
the beginning). What does newList1 now look like and why? Again
draw a picture to show what is going on with the pointers.
- Note that the destructor is called at the end of the
if block because an OrderedList was created inside the block.
- Similar pointer behavior occurs when the default assignment is
used. For example, draw pictures to illustrate what is happening
with newList1 and newList2 near the end of the program.
- Remove the comments that comment out the copy constructor
and the assignment operator (in both olist.h and olist.cc)
and run the program. You should now observe
correct behavior.
- Finally, the current destructor does nothing but print a message.
It should actually remove and delete each node on the list.
Similarly the assignment operator should reclaim all nodes from
the current list before reassigning the object.
So, modify the class as follows:
-
Add a function to actually delete the nodes in the list and
return them to free store.
- Update the destructor to call the function to delete the
nodes.
- Similarly add code in the assignment operator to delete
the nodes in the current list before reassigning.
Using Files
The program FileIO.cc shows how to
open files, use them (read from and write to), and close them.
It reads a list of integers and finds the sum and average.
It prints the number of integers read, the sum, and the average
to another file. Note that the file stream must explicitly be
closed.
Exercise:
- Study the program to see what is going on.
- Create an input file the meets the specifications - include
at least 5 integers for the data. Run your program then examine
the output file.
- Run the program entering the name of a non-existent file
for the input file. What happens?
- Delete a data integer from your input file. Run the program to
see what happens.
- Change the parameter type to the function processInput
from ifstream to istream. In the C++ library, an
ifstream is derived from an istream; that is, an ifstream is an
istream. Compile the program. What is the error and what does it
mean?
- Now, move the statement inFile.close() from inside the
function processInput to main just before
the call to the function writeOutput. Compile the program.
Why are there no errors this time? Link and run the program to
make sure it is correct.
Hand in: Written answers to questions plus a copy of
the olist.cc program that you modified.