More About Classes and Objects
Destructors:
In addition to the special Constructor function, classes also have a special
function called a destructor.
Declaration:
The destructor looks like the default constructor (constructor with
no parameters), but with a ~ in front. Destructors cannot have parameters,
so there can only be one destructor for a class. Example: The
destructor for the Fraction class would be:
~Fraction();
Like the constructor, this function is called automatically (not explicitly)
-
A constructor is called automatically when an object is created.
-
A destructor is called automatically right before an object is deallocated
by the system (usually when it goes out of scope).
The destructor's typical job is to do any clean-up tasks (usually
involving memory allocation) that are needed, before an object is deallocated.
However, like a constructor, a destructor is a function and can do other
things, if desired.
Compile and run this example to see when
constructors and destructors are invoked.
const Member Functions
Another use of the keyword const is in the context of a member
function of a class. If the word const is applied at the end of
the declaration, it is a signal that the function will not be allowed to
modify the object (i.e. any of it's member data) when it is executed.
Example:
class Thing
{
public:
Thing();
void Show() const; // function cannot modify member data
void SetPrice(double p); // function CAN modify member data
private:
double price;
int id; // member data
};
One might ask why even use const, if the programmer is really
careful to make the functions do only what they should. There are two
good reasons for appropriate uses of the keyword const (wherever
applicable):
- The compiler will enforce it. A very good double-check mechanism, even
if the programmer was trying to be careful.
- Good communication to the user of the class, function, variable, etc.
The declaration shows the allowable use, and the user has assurance as to
whether a function could change a variable/object/parameter or
not
Example from Deitel that uses const member functions
Writing a class from scratch:
In-Class example:
Some techniques and hints:
-
Test compilation frequently, by writing stubs for the functions
(i.e. empty function bodies) so that compilation could occur at any
time.
This way, we can write one function at a time, then compile it.
This
process makes debugging much easier!
-
Test functionality frequently. As new functions are written,
test
them with calls in a driver program (i.e. a simple main program
written solely for the purpose of testing.
Composition (the "has-a" relationship):
When we have objects of one type embedded inside an object of another type
(i.e. an object of one type is member data of another class), then the
objects have what is known as a "has-a" relationship. This
is also known as composition. This technique follows the idea
of "tool building". Objects of one class type can be used as member
data in another class -- the embedded object is essentially a component
of the new class. A an object of a previously built type can become
a building block for creating a new type.
Note: The term "has-a" comes from the natural way to speak about
such a relationship. If Car is a class, and it contains a
member data item of type Motor (another class), then it is natural
to say "the Car obect has a Motor obect inside it"
Timer class example:
This example contains two classes -- Display and Timer. You can access
the code here.
The files are:
-
digitime.h -- header file, which consists of declarations for the
Display class and the Timer class
-
digitime.cpp -- implementation file, which consists of member
function definitions for the Display and Timer classes
-
main.cpp -- main program file, which is a short driver program to
test our timer.
Note the relationship between the classes. Two Display
objects
are used as member data in the Timer class declaration -- they are
named hours and minutes (these are variables).
class Timer
{
public:
// public member functions
private:
// Display objects declared as private data of a Timer object
Display hours, minutes;
};
This is the "has-a" relationship -- a Timer object "has" two objects
of type Display embedded inside of it, as components.
Also note the following:
-
The user of the Timer is the main program (so the main program will
be calling the timer's functions)
-
The user of the Display objects is the Timer object (so the Timer
object will be calling Display functions through the objects hours
and minutes)
Another example of classes in a "has-a" relationship:
SodaMachine class