Friend functions, Functions on Objects

advertisement
-------------------------------------------------------------------------------------------CSC 215 -- Week 7
-------------------------------------------------------------------------------------------Friend functions, Functions on Objects
Some functions are strongly and almost solely related to a particular ADT. i.e.
Time add(Time t1, Time t2)
{
Time temp;
temp.hour = t1.getHour() + t2.getHour();
temp.minutes = t1.getMinutes() + t2.getMinutes();
temp.hour = temp.minutes / 60; // round up minutes to hours
temp.minutes = temp.minutes % 60; // truncate excess minutes
return temp;
}


Using member functions to access variables lengthens the instruction path of
operations and that increases the time required to execute an operation.
The performance of the function could be improved by having the function access
private class members directly
 The function deals with two objects from one type of class -- Time
 The function needs details about the internal structure of the classes -it uses multiple class variables via their accessor functions.
 The function seems basic to the class.
 ADT benefits if the function is part of the class.
Friend function
an ordinary, non-class member function which has access to all
data items of one or more classes.
When creating a friend function,
 put the prototype inside the class definition preceded by the "friend" keyword
 The coded implementation of the function should not contain the
 "friend" keyword
 scope resolution "::" operator
class Time
{ int hour;
int minutes;
public:
int getHour();
int getMinutes();
friend Time add(Time t1, Time t2); // "friend" keyword needed
};
Time add(Time t1, Time t2)// no "friend" nor scope resolution needed
// friend functions are defined like ordinary functions but can
// access private members and the dot operator is not used when
// the function is called
{Time temp;
temp.hour = t1.hour + t2.hour;
temp.minutes = t1.minutes + t2.minutes;
temp.hour = temp.minutes / 60; // round up minutes to hours
temp.minutes = temp.minutes % 60; // truncate excess minutes
return temp;
}
1
--------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------CSC 215 -- Week 7
-------------------------------------------------------------------------------------------//
#ifndef DATEWORK_H
#define DATEWORK_H
#include <iostream>
friend function
// test if this code has been called before, if not, then define it; otherwise skip
// When this is defined, it will process everything till the next #endif
// provides ostream
namespace DateWorkSpace
{
class DateWork
{
public:
// create a separate namespace distinct from std namespace;
DateWork();
DateWork(int year);
DateWork(int month, int year);
DateWork(int month, int day, int year);
int getDay();
int getMonth();
int getYear();
void add1Year();
friend std::ostream& operator <<(std::ostream& outs, const DateWork& the_object);
friend bool operator ==(const DateWork& date1, const DateWork& date2);
friend bool operator !=(const DateWork& date1, const DateWork& date2);
friend bool operator <=(const DateWork& date1, const DateWork& date2);
friend bool operator >=(const DateWork& date1, const DateWork& date2);
friend bool operator >(const DateWork& date1, const DateWork& date2);
friend bool operator <(const DateWork& date1, const DateWork& date2);
private:
int year;
int month;
int day;
};
}
#endif
----------------------------------------------------------------------#include <iostream>
#include "datework.h"
int main( )
{
using namespace std;
using namespace DateWorkSpace;
DateWork date1;
cout << date1 << endl;
DateWork date2(2010);
cout << date2 << endl;
DateWork date3(9,2011);
cout << date3 << endl;
DateWork date4(12,24,2011);
cout << date4 << endl;
if (date1 == date2)
cout << date1 << " == " << date2 << endl;
else
2
--------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------CSC 215 -- Week 7
-------------------------------------------------------------------------------------------cout << date1 << " NOT == " << date2 << endl;
if (date1 != date2)
cout << date1 << " != " << date2 << endl;
else
cout << date1 << " NOT != " << endl;
if (date1 <= date2)
cout << date1 << " <= "<< date2 << endl;
else
cout << date1 << " NOT <= "<< date2 << endl;
if (date1 >= date2)
cout << date1 << " >= " << date2 << endl;
else
cout << date1 << " NOT >= " << date2 << endl;
if (date1 > date2)
cout << date1 << " > "<< date2 << endl;
else
cout << date1 << " NOT > "<< date2 << endl;
if (date1 < date2)
cout << date1 << " < "<< date2 << endl;
else
cout << date1 << " NOT < "<< date2 << endl;
for (int i = 0; i < 10; i++)
{
date1.add1Year();
cout << "date1 is now " << date1 << endl;
}
cout << "date1's month is " << date1.getMonth() << endl;
cout << "date1's day is " << date1.getDay() << endl;
cout << "date1's year is " << date1.getYear() << endl;
return EXIT_SUCCESS;
}
----------------------------------------------------------------------#include <iostream>
#include <cctype>
#include <cstdlib>
#include <cassert>
#include "datework.h"
using namespace std;
namespace DateWorkSpace
{
DateWork::DateWork()
{
day = 1;
month = 1;
3
--------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------CSC 215 -- Week 7
-------------------------------------------------------------------------------------------year = 2001;
}
DateWork::DateWork(int y)
{
day = 1;
month = 1;
year = y;
}
DateWork::DateWork(int m, int y)
{
assert(m >= 1);
assert(m <= 12);
day = 1;
month = m;
year = y;
}
DateWork::DateWork(int m, int d, int y)
{
assert(m >= 1);
assert(m <= 12);
assert(d >= 1);
assert(d <= 31);
day = d;
month = m;
year = y;
}
void DateWork::add1Year()
{
year++;
}
int DateWork::getYear()
{
return year;
}
int DateWork::getMonth()
{
return month;
}
int DateWork::getDay()
{
return day;
}
ostream& operator <<(ostream& outs, const DateWork& the_object)
{
outs << the_object.month << '/';
outs << the_object.day << '/';
outs << the_object.year;
4
--------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------CSC 215 -- Week 7
-------------------------------------------------------------------------------------------return outs;
}
bool operator ==(const DateWork& date1, const DateWork& date2)
{
if (date1.day == date2.day
&& date1.month == date2.month
&& date1.year == date2.year)
return true;
else
return false;
}
bool operator !=(const DateWork& date1, const DateWork& date2)
{
return !(date1 == date2);
}
bool operator <=(const DateWork& date1, const DateWork& date2)
{
long d1,d2;
d1 = date1.year * 10000 + date1.month * 100 + date1.day;
d2 = date2.year * 10000 + date2.month * 100 + date2.day;
if (d1 <= d2)
return true;
else
return false;
}
bool operator >=(const DateWork& date1, const DateWork& date2)
{
long d1,d2;
d1 = date1.year * 10000 + date1.month * 100 + date1.day;
d2 = date2.year * 10000 + date2.month * 100 + date2.day;
if (d1 >= d2)
return true;
else
return false;
}
bool operator <(const DateWork& date1, const DateWork& date2)
{
return !(date1 >= date2);
}
bool operator >(const DateWork& date1, const DateWork& date2)
{
return !(date1 <= date2);
}
}
----------------------------------------------------------------------
5
--------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------CSC 215 -- Week 7
-------------------------------------------------------------------------------------------Operator Overloading

User-defined classes do not allow standard C++ syntax, such as
if (date3 == date4)
cout << "\n The dates are equal";
else
cout << "\n The dates are not equal";

It is possible to overload C++ operators for classes.
 C++ predefined "operators"
 arithmetic operators: +, -, *, /, %
 relational operators: <, <=, ==, !=, >, >=
 assignment operator: =
 logical operators: &&, ||, !
 input/output operators: <<, >>

When overloading C++ operators
 One or more classes should be passed as arguments to the operator.
 Use only the C++ predefined "operators".
 The number of arguments required by the operator remains the same
 The precedence of the operator remains the same
 The overloaded operator can be a regular function or a friend function.
Friend functions can be used to overload operators.

class Time
{...
friend Time operator +(Time t1, Time t2);
};
Operators are overloaded by functions with an reserved word "operator" in front
of the operator symbol.
Time operator + (const Time& t1, const Time& t2)
// overloaded "operator +" for Time class
{
Time temp;
temp.hour = t1.hour + t2.hour;
temp.minutes = t1.minutes + t2.minutes;
temp.hour = temp.hour + (temp.minutes / 60) ;
temp.minutes = temp.minutes % 60; // truncate excess minutes
return temp;
}

Now the syntax can be made more similar to standard C++ notation
Time t3 = t1 + t2; // function call to overloaded operator+
6
--------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------CSC 215 -- Week 7
-------------------------------------------------------------------------------------------Prototypes for overloading >> and <<:
class Class_name
{
public:
friend istream& operator >> (istream& inStreamPointer, Class_Name& ObjectName)
friend ostream& operator << (ostream& outStreamPointer, Class_Name& ObjectName)
}
Definitions:
istream& operator >> (istream& inStreamPointer, Class_Name& ObjectName)
{…}
ostream& operator << (ostream& outStreamPointer, Class_Name& ObjectName)
{…}
-----------------------------------------------------------------------

Discuss Display 8.8 Savitch
-----------------------------------------------------------------------

Discuss Separate Program compilation (Display 8.9, 8.10, 8.11 Savitch)
----------------------------------------------------------------------//This is the HEADER FILE dtime.h. The INTERFACE for the class DigitalTime.
//Values of this type are times of day. The values are input and output in
//24 hour notation as in 9:30 for 9:30 AM and 14:45 for 2:45 PM.
// Since C++ does not allow a class to be defined more than once,
#ifndef DTIME_H
// test if this code has been called before, if not, then define it; otherwise skip
#define DTIME_H
// When this is defined, it will process everything till the next #endif
#include <iostream>
using namespace std;
namespace savitchdtime // create a separate savitchdtime namespace distinct from std namespace;
{
class DigitalTime
{
public:
friend bool operator ==(const DigitalTime& time1, const DigitalTime& time2);
//Returns true if time1 and time2 represent the same time;
//otherwise, returns false.
DigitalTime(int the_hour, int the_minute);
//Precondition: 0 <= the_hour <= 23 and 0 <= the_minute <= 59.
//Initializes the time value to the_hour and the_minute.
DigitalTime( );
//Initializes the time value to 0:00 (which is midnight).
void advance(int minutes_added);
//Precondition: The object has a time value.
//Postcondition: The time value has been changed to minutes_added minutes later.
void advance(int hours_added, int minutes_added);
//Precondition: The object has a time value.
//Postcondition: The time value has been advanced
//hours_added hours plus minutes_added minutes.
friend istream& operator >>(istream& ins, DigitalTime& the_object);
7
--------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------CSC 215 -- Week 7
-------------------------------------------------------------------------------------------//Overloads the >> operator for input values of type DigitalTime.
//Precondition: If ins is a file input stream, then ins has already been
//connected to a file.
friend ostream& operator <<(ostream& outs, const DigitalTime& the_object);
//Overloads the << operator for output values of type DigitalTime.
//Precondition: If outs is a file output stream, then outs has already been
//connected to a file.
private:
int hour;
int minute;
};
}
#endif //DTIME_H
----------------------------------------------------------------------// This is the IMPLEMENTATION file, dtime.cpp, of the ADT DigitalTime.
//The interface for the class DigitalTime is in the header file dtime.h.
#include <iostream>
#include <cctype>
#include <cstdlib>
#include "dtime.h"
using namespace std;
namespace savitchdtime
{
//These PROTOTYPES are for the definition of the overloaded input operator >>:
void read_hour(istream& ins, int& the_hour);
//Precondition: Next input in the stream ins is a time in notation, like 9:45 or 14:45.
//Postcondition: the_hour has been set to the hour part of the time.
//The colon has been discarded and the next input to be read is the minute.
void read_minute(istream& ins, int& the_minute);
//Reads the minute from the stream ins after read_hour has read the hour.
int digit_to_int(char c);
//Precondition: c is one of the digits '0' through '9'.
//Returns the integer for the digit; e.g., digit_to_int('3') returns 3.
bool operator ==(const DigitalTime& time1, const DigitalTime& time2)
{ return (time1.hour == time2.hour && time1.minute == time2.minute); }
//Uses iostream and cstdlib:
DigitalTime::DigitalTime(int the_hour, int the_minute)
{
if (the_hour < 0 || the_hour > 23 || the_minute < 0 || the_minute > 59)
{
cout << "Illegal argument to DigitalTime constructor.";
exit(1);
}
else
{
hour = the_hour;
minute = the_minute;
}
}
8
--------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------CSC 215 -- Week 7
-------------------------------------------------------------------------------------------DigitalTime::DigitalTime( )
{
hour = 0;
minute = 0;
}
void DigitalTime::advance(int minutes_added)
{
int gross_minutes = minute + minutes_added;
minute = gross_minutes%60;
int hour_adjustment = gross_minutes/60;
hour = (hour + hour_adjustment)%24;
}
void DigitalTime::advance(int hours_added, int minutes_added)
{
hour = (hour + hours_added)%24;
advance(minutes_added);
}
//Uses iostream:
istream& operator >>(istream& ins, DigitalTime& the_object)
{
read_hour(ins, the_object.hour);
read_minute(ins, the_object.minute);
return ins;
}
//Uses iostream:
ostream& operator <<(ostream& outs, const DigitalTime& the_object)
{
outs << the_object.hour << ':';
if (the_object.minute < 10)
outs << '0';
outs << the_object.minute;
return outs;
}
int digit_to_int(char c)
{
return ( int(c) - int('0') );
}
//Uses iostream, cctype, and cstdlib:
void read_hour(istream& ins, int& the_hour)
{
char c1, c2;
ins >> c1 >> c2;
if ( !( isdigit(c1) && (isdigit(c2) || c2 == ':' ) ) )
{
cout << "Error illegal input to read_hour\n";
exit(1);
}
9
--------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------CSC 215 -- Week 7
-------------------------------------------------------------------------------------------if (isdigit(c1) && c2 == ':')
{
the_hour = digit_to_int(c1);
}
else //(isdigit(c1) && isdigit(c2))
{
the_hour = digit_to_int(c1)*10 + digit_to_int(c2);
ins >> c2;//discard ':'
if (c2 != ':')
{
cout << "Error illegal input to read_hour\n";
exit(1);
}
}
if ( the_hour < 0 || the_hour > 23 )
{
cout << "Error illegal input to read_hour\n";
exit(1);
}
}
//Uses iostream, cctype, and stdlib:
void read_minute(istream& ins, int& the_minute)
{
char c1, c2;
ins >> c1 >> c2;
if (!(isdigit(c1) && isdigit(c2)))
{
cout << "Error illegal input to read_minute\n";
exit(1);
}
the_minute = digit_to_int(c1)*10 + digit_to_int(c2);
if (the_minute < 0 || the_minute > 59)
{
cout << "Error illegal input to read_minute\n";
exit(1);
}
}
}//end savitchdtime
----------------------------------------------------------------------//This is the APPLICATION FILE:
// This program demonstrates use of the class DigitalTime.
#include <iostream>
#include "dtime.h"
int main( )
{
10
--------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------CSC 215 -- Week 7
-------------------------------------------------------------------------------------------using namespace std;
using namespace savitchdtime;
DigitalTime clock, old_clock;
cout << "Enter the time in 24 hour notation: ";
cin >> clock;
old_clock = clock;
clock.advance(15);
if (clock == old_clock)
cout << "Something is wrong.";
cout << "You entered " << old_clock << endl;
cout << "15 minutes later the time will be "
<< clock << endl;
clock.advance(2, 15);
cout << "2 hours and 15 minutes after that\n"
<< "the time will be "
<< clock << endl;
return 0;
}
----------------------------------------------------------------------/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
PROGRAMING ASSIGNMENT 6 (due next week)
Pick one assignment.
student.
Only 1 assignment will be graded per
Both program problems should be coded so that the program could
be tested with keyboard input and screen output until the user is
ready to quit.
All assignments receive a 2-point bonus if received by email by
midnight two days before date due.
Problem 1)
(10 points) Programming Project 1 page 523.
Add function interval_since to DigitalTime class
Problem 2)
(15 points) Programming Project 5 page 525.
Define an ADT for rational numbers.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11
--------------------------------------------------------------------------------------------
Download