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 ( ) )