09Friend

advertisement
Friend Functions
Problem
 Assuming
two Complex objects
 How would one add two numbers?
W+X
Complex operator+(const Complex& w, const Complex& x);
Whose member function is it? W? X?
Whose data elements are changed? W? X?
Neither; The operation is outside both W and X
A similar operation: cout << W;
Solution:
A
"compromise" mechanism
– Class granting non-member function permission
to access its data members.
 By
– Declaring non-member function within class
– Preceding its declaration with keyword friend.
Friend Functions
 not
member functions of class X
 have access to data members in class X
 named as a friend in class X’s header
 defined in class X’s implementations file

"outside" an object
– When friend function operates on an object it
receives the object via a parameter.
Friend functions
 declared
within class
(prepend friend)
friend int operator< (const Strings& S1, const Strings& S2);
 defined
in implementation file (no friend, no ::)
int operator< (const Strings& S1, const Strings& S2)

See friend/strings.h & strings.cpp
19. Differentiate among member functions,
global functions and friend functions.

Virtual functions must be members

operator>> & operator<< are never members

Only non-member functions get their type
conversions on their left-most argument
Rational r = 2 * Rational(3,4);
operarator* must be Friend or auxiliary function

Everything else should be member functions
Friend example
/***** I/O Functions *****/
/* --- ostream output
Receives: An ostream Out and a Time object T
Output:
data members of Time object in standard
format.
Passes back:
ostream Out with T inserted
Return value:
Out
*************************************************/
friend ostream& operator<<(ostream& Out, const Time& T);
Definition in Time.cpp remains unchanged.
Overloading Output for Objects
How could we output an object using
cout << "We'll be eating at " << MealTime << endl;
instead of
cout << "We'll be eating at " ;
MealTime.PrintTime();
cout << endl;
Place definition in Time.cpp
//----- Function to implement ostream output ---ostream& operator<<(ostream& Out, const Time& T)
{
Out << T.Hour_ << ':'
<< (T.Minute_ < 10 ? "0" : "") << T.Minute_
<< ' ' << T.AMorPM_ << ".M. ("
<< (T.MilTime_ < 100 ? "0" : "") << T.MilTime_
<< " mil. time)”;
return Out;
}
Output example
Time
MealTime,
BedTime(11, 30, 'P');
. . .
MealTime.Set(5, 30, 'P');
cout << "Eat at " << MealTime
<< "\nand sleep at " << BedTime;
Execution:
Eating at 5:30 P.M. (1730 mil. time)
and sleep at 11:30 P.M. (2330 milt time)
Time Class Input:
In Time.h, declare operator>>( ) as a friend function:
/* --- istream input
Receives: An istream In and a Time object T
Input:
Values for the data members of T.
Passes back:
istream In with values removed
T with values stored in data
members
Return value:
In
Note: Input times in format hh:mm xM
***************************************************/
friend istream& operator>>(istream& In, Time& T);
Add to Time.cpp
//----- Function to implement istream input ---istream& operator>>(istream& In, Time& T)
{
int
Hours, Minutes;
char
Ch,
// gobbles up extra characters
AMPM;
In >> Hours >> Ch >> Minutes >> AMPM >> Ch;
T.Set(Hours, Minutes, AMPM);
return In;
}
Time
MealTime, BedTime;
. . .
cout << "Enter meal time and bedtime (hh:mm xM): ";
cin >> MealTime >> BedTime;
cout << "We'll be eating at '' << MealTime << endl;
cout << "We'll hit the hay at " << BedTime << endl;
Execution:
Enter meal time and bedtime (hh:mm xM): 5:30 PM 11:30
PM
We'll be eating at 5:30 P.M. (530 mil. time)
We'll hit the hay at 11:30 P.M. (2330 milt time)
Enter
12:15
We'll
We'll
meal time and bedtime (hh:mm xM): 5:30 PM
AM
be eating at 5:30 P.M. (530 mil. time)
hit the hay at 12:15 A.M. (015 mil. time)
Class Scope Rule:
 Members
of a class are local to the
class.
 Private members can be accessed only
within class
– by member functions
– by friends of the class
 Public
members class can be accessed
outside using dot notation
Adding Relational Operator: <
Less-than: (Time, Time) --> Boolean
Receives: Two Time objects
Returns: True if first Time object is less
than second; false otherwise.
Is operator< a member function?
Does it belong inside the Time class?
– it can operate on a Time object that
contains it
Does it belong outside the class?
– it can operate on any Time object
Answer: The latter.
Not a member function.
Is operator< a friend function?
Does it need access to data members?
Answer: Yes.
Add to Time.h:
/***** Relational operators *~***/
/* --- operator< determines if one Time is less than
another Time
Receive: Times T1 and T2
Return: True (1) if T1 < T2, false (O) otherwise. */
friend short operator<(const Time& T1, const Time& T2)
{
return (Tl.MilTime_ < T2.MilTime_);
};
Because of simplicity of this function we put it its
definition in Time.h.
Adding Advance Function
 Advance:
(Time, Hours, Minutes) --> Time
– Increments Time object by Hours / Minutes

Should it be a member function?
– Does it belong inside the Time class
– from which it can operate on the Time object that
contains it?

Answer: Yes
Add to Time.h:
/***** Increment operator *****/
/* --- Advance()
increments a Time by a specified value.
Receive: Hours, the number of hours to add
Minutes, the number of minutes to add
Return: The Time object containing this function
with its data members incremented by
these values.
*/
void Advance(unsigned Hours, unsigned Minutes);
Advance ( ) increments MilTime_ and converts military
time to corresponding standard time and sets Hour_,
Minute_, and AMorPM_.
//----- Function to implement Advance() -----void Time::Advance(unsigned Hours, unsigned Minutes)
{
MilTime_ += 100 * Hours + Minutes;
unsigned
MilHours = MilTime_ / 100,
MilMins = MilTime_ % 100;
MilHours += MilMins / 60;
MilMins %= 60;
MilHours %= 24;
MilTime_ = 100 * MilHours + MilMins;
ToStandard(MilTime_, Hour_, Minute_, AMorPM_);
}
ToStandard( )
Conversion from military to standard time
may be useful in other operations
We add another utility function:
ToStandard ( )
a counterpart to ToMilitary():
Add declaration & def. to Time.cpp
void ToStandard(unsigned MilTime, unsigned& Hours,
unsigned& Minutes, char& AMPM);
/*--- ToStandard converts military time to standard.
Receive: A military time MilTime
Return: Corresponding std time, Hours, Mins, AMPM */
void ToStandard(unsigned MilTime, unsigned& Hours,
unsigned& Minutes, char& AMPM)
{
Hours = (MilTime / 100) % 12;
if (Hours == 0) Hours = 12;
Minutes = MilTime % 100;
AMPM = (MilTime / 100) < 12 ? 'A' : 'P';
}
Testing
cout << "Meal time < Bed time? "
<< (Mealtime < BedTime ? "TRUE\n" : "FALSE\n");
MealTime.Advance(5,15);
cout << "New meal time " << MealTime << endl;
cout << "Meal time < Bed time? ";
<< (Mealtime < BedTime ? "TRUE\n" : "FALSE\n");
Execution:
Enter meal time and bedtime (hh:mm xM): 6:00 PM 11:00 PM
We'll be eating at 6:00 P.M. (1800 mil. time)
We'll hit the hay at 11:00 P.M. (2300 mil. time)
Meal time < Bed time? TRUE
New meal time 11:15 P.M. (2315 milt time)
Meal time < Bed time? FALSE
More to come?
 Possible
additions
 remaining
relational operators
 ++ operator
=
(in place of set ( ) )
+
 += (in place of Advance ( ) )
Download