260 likes | 428 Views
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
E N D
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 meal time and bedtime (hh:mm xM): 5:30 PM 12:15 AM We'll be eating at 5:30 P.M. (530 mil. time) We'll 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 ( ) )