bool before(DayOfYear date1, DayOfYear date2)
{ return ((date1.getMonth() < date2.getMonth())
|| (date1.getMonth() == date2.getMonth()
&& date1.getDay ( ) < date2.getDay ( )));
}
The previous Boolean expression says that date1
is before date2
, provided the month of date1
is before the month of date2
or that the months are the same and the day of date1
is before the day of date2
.
2.
A friend function and a member function are alike in that they both can use any member of the class (either public or private) in their function definition. However, a friend function is defined and used just like an ordinary function; the dot operator is not used when you call a friend function, and no type qualifier is used when you define a friend function. A member function, on the other hand, is called using an object name and the dot operator. Also, a member function definition includes a type qualifier consisting of the class name and the scope resolution operator ::
.
3. The modified definition of the class DayOfYear
is shown below. The part in color is new. We have omitted some comments to save space, but all the comments shown in Display 11.2 should be included in this definition.
class DayOfYear
{
public:
friend bool equal(DayOfYear date1, DayOfYear date2);
friend bool after(DayOfYear date1, DayOfYear date2);
//Precondition: date1 and date2 have values.
//Returns true if date1 follows date2 on the calendar;
//otherwise, returns false.
DayOfYear(int theMonth, int theDay);
DayOfYear();
void input();
void output();
int getMonth();
int getDay();
private:
void checkDate( );
int month;
int day;
};
You also must add the following definition of the function after
:
bool after(DayOfYear date1, DayOfYear date2)
{
return ((date1.month > date2 month))||
((date1.month == date2.month) && (date1.day > date2.day))
}
4. The modified definition of the class Money
is shown here. The part in color is new. We have omitted some comments to save space, but all the comments shown in Display 11.3 should be included in this definition.
class Money
{
public:
friend Money subtract(Money amount1, Money amount2);
//Precondition: amount1 and amount2 have values.
//Returns amount1 minus amount2.
friend bool equal(Money amount1, Money amount2);
Money(long dollars, int cents);
Money(long dollars);
Money();
double getValue();
void input(istream& ins);
void output(ostream& outs);
private:
long allCents;
};
You also must add the following definition of the function subtract
:
Money subtract(Money amount1, Money amount2)
{
Money temp;
temp.allCents = amount1.allCents
− amount2.allCents;
return temp;
}
5. The modified definition of the class Money
is shown here. The part in color is new. We have omitted some comments to save space, but all the comments shown in Display 11.3 should be included in this definition.
class Money
{
public:
friend Money add(Money amount1, Money amount2);
friend bool equal(Money amount1, Money amount2);
Money(long dollars, int cents);
Money(long dollars);
Money();
double getValue();
void input(istream& ins);
void output(ostream& outs);
//Precondition: If outs is a file output stream, then
//outs has already been connected to a file.
//Postcondition: A dollar sign and the amount of money
//recorded in the calling object has been sent to the
//output stream outs.
void output();
//Postcondition: A dollar sign and the amount of money
//recorded in the calling object has been output to the
//screen.
private:
long allCents;
};
You also must add the following definition of the function name output
. (The old definition of output
stays, so that there are two definitions of output
.)
void Money::output()
{
output(cout);
}
The following longer version of the function definition also works:
//Uses cstdlib and iostream
void Money::output()
{
long positiveCents, dollars, cents;
positiveCents = labs(allCents);
dollars = positiveCents/100;
cents = positiveCents%100;
if (allCents < 0)
cout << "−$" << dollars << '.';
else
cout << "$" << dollars << '.';
if (cents < 10)
cout << '0';
cout << cents;
}
You can also overload the member function input
so that a call like
purse.input();
means the same as
purse.input(cin);
And, of course, you can combine this enhancement with the enhancements from previous Self-Test Exercises to produce one highly improved class Money
.
6. If the user enters $−9.95
(instead of −$9.95
), the function input
will read the '$'
as the value of oneChar
, the −9
as the value of dollars
, the '.'
as the value of decimalPoint
, and the '9'
and '5'
as the values of digit1
and digit2
. That means it will set dollars
equal to −9
and cents
equal to 95
and so set the amount equal to a value that represents −$9.00 plus 0.95, which is −$8.05. One way to catch this problem is to test if the value of dollars
is negative (since the value of dollars
should be an absolute value). To do this, rewrite the error message portion as follows:
This code still will not give an error message for incorrect input with zero dollars as in $−0.95
. However, with the material we have learned thus far, a test for this case, while certainly possible, would significantly complicate the code and make it harder to read.
#include <iostream>
using namespace std;
int main( )
{
int x;
cin >> x;
cout << x << endl;
return 0;
}
If the compiler interprets input with a leading 0
as a base-8 numeral, then with input data 077, the output should be 63
. The output should be 77
if the compiler does not interpret data with a leading 0
as indicating base 8.
8. The only change from the version given in Display 11.3 is that the modifier const
is added to the function heading, so the definition is
double Money::getValue() const
{
return (allCents * 0.01);
}
9. The member function input
changes the value of its calling object, and so the compiler will issue an error message if you add the const
modifier.
10. Similarities: Each parameter call protects the caller’s argument from change.
Differences: The call-by-value makes a copy of the caller’s argument, so it uses more memory than a call-by-constant-reference.
11. In the const int x = 17;
declaration, the const
keyword promises the compiler that code written by the author will not change the value of x
.
In the int f() const;
declaration, the const
keyword is a promise to the compiler that code written by the author to implement function f
will not change anything in the calling object.
In the int g(const A& x);
declaration, the const
keyword is a promise to the compiler that code written by the class author will not change the argument plugged in for x
.
12. The difference between a (binary) operator (such as +
, *
, /
, and so forth) and a function involves the syntax of how they are called. In a function call, the arguments are given in parentheses after the function name. With an operator, the arguments are given before and after the operator. Also, you must use the reserved word operator
in the declaration and in the definition of an overloaded operator.
13. The modified definition of the class Money
is shown here. The part in color is new. We have omitted some comments to save space, but all the comments shown in Display 11.5 should be included in this definition.
class Money
{
public:
friend Money operator +(const Money& amount1,
const Money& amount2);
friend bool operator ==(const Money& amount1,
const Money& amount2);
friend bool operator <(const Money& amount1,
const Money& amount2);
//Precondition: amount1 and amount2 have been given
//values.
//Returns true if amount1 is less than amount2;
//otherwise, returns false.
Money(long dollars, int cents);
Money(long dollars);
Money();
double getValue() const;
void input(istream& ins);
void output(ostream& outs) const;
private:
long allCents;
};
You also must add the following definition of the overloaded operator <
:
bool operator <(const Money& amount1,
const Money& amount2)
{
return (amount1.allCents < amount2.allCents);
}
14. The modified definition of the class Money
is shown here. The part in color is new. We have omitted some comments to save space, but all the comments shown in Display 11.5 should be included in this definition. We have included the changes from the previous exercises in this answer, since it is natural to use the overloaded <
operator in the definition of the overloaded <=
operator.
class Money
{
public:
friend Money operator +(const Money& amount1,
const Money& amount2);
friend bool operator ==(const Money& amount1,
const Money& amount2);
friend bool operator <(const Money& amount1,
const Money& amount2);
//Precondition: amount1 and amount2 have been given
//values.
//Returns true if amount1 is less than amount2;
//otherwise, returns false.
friend bool operator <=(const Money& amount1,
const Money& amount2);
//Precondition: amount1 and amount2 have been given
//values.
//Returns true if amount1 is less than or equal to
//amount2; otherwise, returns false.
Money(long dollars, int cents);
Money(long dollars);
Money();
double getValue() const;
void input(istream& ins);
void output(ostream& outs) const;
private:
long allCents;
};
You also must add the following definition of the overloaded operator <=
(as well as the definition of the overloaded operator <
given in the previous exercise):
bool operator <=(const Money& amount1,
const Money& amount2)
{
return ((amount1.allCents < amount2.allCents)
||(amount1.allCents == amount2.allCents));
}
15. When overloading an operator, at least one of the arguments to the operator must be of a class type. This prevents changing the behavior of +
for integers. Actually, this requirement prevents changing the effect of any operator on any built-in type.
//Uses cmath (for floor):
Money::Money(double amount)
{
allCents = floor(amount * 100);
}
This definition simply discards any amount that is less than one cent. For example, it converts 12.34999
to the integer 1234
, which represents the amount $12.34. It is possible to define the constructor to instead do other things with any fraction of a cent.
istream& operator >>(istream& ins, Pairs& second)
{
char ch;
ins >> ch; //discard initial '('
ins >> second.f;
ins >> ch; //discard comma ','
ins >> second.s;
ins >> ch; //discard final ')'
return ins;
}
ostream& operator <<(ostream& outs, const Pairs& second)
{
outs << '(';
outs << second.f;
outs << ','; //You might prefer ","
//to get an extra space
outs << second.s;
outs << ')';
return outs;
}
//Uses iostream:
istream& operator >>(istream& ins, Percent& theObject)
{
char percentSign;
ins >> theObject.value;
ins >> percentSign;//Discards the % sign.
return ins;
}
//Uses iostream:
ostream& operator <<(ostream& outs,
const Percent& aPercent)
{
outs << aPercent.value << '%';
return outs;
}
struct Score
{
int homeTeam;
int opponent;
};
Score game[10];
//Reads in 5 amounts of money, doubles each amount,
//and outputs the results.
#include <iostream>
<The definitions for the Money class go here.>
int main()
{
using namespace std;
Money amount[5];
int i;
cout << "Enter 5 amounts of money:\n";
for (i = 0; i < 5; i++)
cin >> amount[i];
for (i = 0; i < 5; i++)
amount[i] = amount[i] + amount[i];
cout << "After doubling, the amounts are:\n";
for (i = 0; i < 5; i++)
cout << amount[i] << " ";
cout << endl;
return 0;
}
(You cannot use 2 * amount[i]
, since *
has not been overloaded for operands of type Money
.)
21. See answer 22.
22. This answer combines the answers to this and the previous Self-Test Exercise. The class definition would change to the following. (We have deleted some comments from Display 11.10 to save space, but you should include them in your answer.)
class TemperatureList
{
public:
TemperatureList();
int getSize( ) const;
//Returns the number of temperatures on the list.
void addTemperature(double temperature);
double getTemperature(int position) const;
//Precondition: 0 <= position < getSize( ).
//Returns the temperature that was added in position
//specified. The first temperature that was added is
//in position 0.
bool full() const;
friend ostream& operator <<(ostream& outs,
const TemperatureList& theObject);
private:
double list[MAX_LIST_SIZE];//of temperatures in
//Fahrenheit
int size; //number of array positions filled
};
You also need to add the following member function definitions:
int TemperatureList::getSize() const
{
return size;
}
//Uses iostream and cstdlib:
double TemperatureList::getTemperature (int position) const
{
if ((position >= size) || (position < 0))
{
cout << "Error:"
<< " reading an empty list position.\n";
exit(1);
}
else
return (list[position]);
}
23. The constructor is named MyClass
, the same name as the name of the class. The destructor is named ~MyClass
.
24. The dialogue would change to the following:
What is your name?
Kathryn Janeway
We are Borg
We will meet again Kathryn Janeway
Good-bye cruel world! The short life of
this dynamic array is about to end.
Good-bye cruel world! The short life of
this dynamic array is about to end.
End of demonstration
25. The StringVar
before the ::
is the name of the class. The StringVar
right after the ::
is the name of the member function. (Remember, a constructor is a member function that has the same name as the class.) The StringVar
inside the parentheses is the type for the parameter stringObject
.
A destructor is a member function of a class. A destructor’s name always begins with a tilde, ~
, followed by the class name.
A destructor is called when a class object goes out of scope.
A destructor actually does whatever the class author programs it to do!
A destructor is supposed to delete dynamic variables that have been allocated by constructors for the class. Destructors may also do other cleanup tasks.
27. In the case of the assignment operator =
and the copy constructor, if there are only built-in types for data, the default copy mechanism is exactly what you want, so the default works fine. In the case of the destructor, no dynamic memory allocation is done (no pointers), so the default do-nothing action is again what you want.