Saint Louis University |
Computer Science P125
|
Dept. of Math & Computer Science |
Classes
are the way programmers raise the level of abstraction in problem solving above
the level of scalars (and vectors or arrays). In creating a class, the
programmer is creating a re-usable representation of a concept used in problem
solving. The more complex the class is, the less complex the rest of the
program can be.
Your goal today is to write a program to
accomplish the following task. Assume you have some tracks to burn to a CD and
you need to know if they will fit. Pretending there isn't a better way to do
this, you decide to write a program to add the times of the tracks together to
see if they will fit within on one CD.
In doing so, we wish to have you develop your own Time classÉ
á
int
hours
á
int
minutes
á
float
seconds
á
Time()
-- constructor
á
void
setTime(int, int, float) Ð set the value of a Time object with default parameter
values
á
int
getHours()
á
int
getMinutes()
á
float
getSeconds()
á
Time
add (Time)
Ð returns the sum of a Time object and another given Time
á
bool
lessThan(Time)
Ð find out if one Time is less than (or before) another
g++ -o burn burn.cpp
time.cpp -Wall
Rather
than walk you through the precise design of your lab problem, the remainder of
this document walks you through the design of a similar class, namely one to represent Money. You should read through this
discussion, and hopefully can adapted the described techniques to design your
own Time class.
Suppose you have a problem that deals with
money. You can represent dollars and cents as one double, it is not OK to have
fractions of cents. An alternative is to represent dollars and cents as two
values. Best is to create a class to represent money. We can begin with just
(class header on left, program on right:
//file:
money.h class
Money { int dollars; int cents; }; |
#include
"money.h" int
main() { Money mine, yours, sum; sum = mine + yours; } |
Of course, we know from last week that the
compiler does not know what to do with Money objects unless we define the
methods. To be able to add Money objects, you must either overload the +
operator, or define an addition method (the choice is a matter of stylistic
preference). Seeing that we need an addition method, we could edit the header
file to be (the ordering of things in the class is also a matter of
stylistic-preference). Of course, also needed is the money.cpp file that
defines how the money is added (we ignore this for the moment).
//file:
money.h class
Money { Money plus(Money); int dollars; int cents; }; |
#include
"money.h" int
main() { Money mine, yours, sum; sum =
mine.plus(yours); } |
When attempting to compile this, there is an
error. The compiler says something about plus being private. The correction is to make plus() public. The change is
shown below. However, the change shown below makes everything public. The
consequence is that a programmer using the time class can freely access the
data members as well (i.e., dollars and cents), which makes the code
on the right possible.
//file:
money.h class
Money { public: Money plus(Money); int dollars; int cents; }; |
#include
"money.h" int
main() { Money mine, yours, sum; sum = mine.plus(yours); mine.cents = 100; yours.cents = -1000; } |
The code on the right should make you
uncomfortable. It is possible to have cents values that make no sense. For
example, there should never be a cents value greater than 99 or less than
Ð99. In addition, with the data
members public it is possible to have positive dollars and negative cents
(nonsense!). The fix is to make data member private. Data members should be
private in every class. See changed code É
//file: money.h class Money { public: Money
plus(Money); private: int
dollars; int
cents; }; |
#include
"money.h" int
main() { Money mine, yours, sum; sum = mine.plus(yours); mine.cents = 100; //illegal yours.cents = -1000; //illegal } |
Now that the data
members are private (and for good reason), we need methods for setting (and
getting values) of Money objects. The natural thing to do is write void setDollars(int), setCents(int). This gets a little
tedious. We could write a void
setValue(int,
int) method
instead of the individual set
methods. The class interface (a.k.a, the class header file) shown below has the
new setValue() method. The code on the
right shows the use of that method.
//file: money.h class Money { public: Money
plus(Money additional); void
setValue(int d, int c); private: int
dollars; int
cents; }; |
#include
"money.h" int
main() { Money mine, yours, sum; mine.setValue(99,
0); //$99.00 yours.setValue(0, 99);
//$0.99 sum = mine.plus(yours); } |
Notice that when using the setValue() method,
two values (i.e, dollars and cents) are needed even when the value is just a
dollar value (no cents) or value a cents value (no dollars). One possible
change (dare we say, improvement) is to provide a default parameter value for the setValue() method (see the change
to the setValue() method in the money.h
file, below on left). With the default value, the parameter with a default
value becomes optional. See the example at the right, below.
//file: money.h class Money { public: Money
plus(Money additional); void setValue(int d, int c
= 0); void
setDollars(int d); void
setCents(int c); int
getDollars(); int
getCents(); private: int
dollars; int
cents; }; |
#include
"money.h" int
main() { Money mine, yours, sum; mine.setValue(99); // $99.00 yours.setValue(0, 99); // $0.99 sum = mine.plus(yours); } |
When writing a method, it is acceptable (and often a good idea) to use other methods. In the implementation of setValue(), using the setDollar() and setCents() methods make setValue() easy. This is particularly true with the cents to dollars conversion provided by the setCents() method.
//file:
money.cpp #include
"money.h" void
Money::setValue(int d, int c) { setDollars(d); setCents(c); } |
//file:
money.cpp void
Money::setCents(int c) { cents = c % 100; dollars += c / 100; } void
Money::setDollars(int d) { dollars = d; } |
Every class should have
(at least) one constructor. A constructor is a method whose name is the same as
the class. For Money class, every constructor of Money class is called Money.
Constructors are used when an object is created. Notice there is no return type
specified for a constructor.
//file: money.h class Money { public: Money(); Money(int
d, int c = 0); Money
plus(Money additional); void setValue(int d, int c
= 0); void setDollars(int d); void
setCents(int c); int
getDollars(); int
getCents(); private: int
dollars; int
cents; }; |
//file:
money.cpp #include
"money.h" Money::Money() { dollars = 0; cents = 0; } Money::Money(int
d, int c) { setValue(d, c); } |
Class construction is done in two parts (i.e,, interface and header, two files: .h and .cpp) and there is a separate program file. Compiling the class and the program can be done all together, or separately.
Compiling the class separately from the program allow you to avoid compiling the class when the program (but not the class) has changed. The class can be compiled into an object file. The object file is later linked to the program file that uses the class.