220 likes | 394 Views
Friend Functions. Friend Functions. An ordinary function that is given special access to the private members of a class NOT a member function of the class Prototype is listed in the class definition Keyword friend goes in front of the prototype. Program to demonstrate the function equal.
E N D
Friend Functions • An ordinary function that is given special access to the private members of a class • NOT a member function of the class • Prototype is listed in the class definition • Keyword friend goes in front of the prototype
Program to demonstrate the function equal. class DayOfYear { public: DayOfYear(int the_month, int the_day); //Initializes the date according to the arguments. DayOfYear( ); //Initializes the date to January first. void input( ); void output( ); int get_month( ); //Returns the month, 1 for January, 2 for February. int get_day( ); //Returns the day of the month. private: int month; int day; };
This is the prototype for a function defined outside the class. It is NOT a member function, but rather a typical function. bool equal(DayOfYear date1, DayOfYear date2); //Precondition: date1 and date2 have values. //Returns true if date1 and date2 represent the same date, //otherwise returns false. int main( ) { DayOfYear today, bach_birthday(3, 21); cout << "Enter today's date:\n"; today.input( ); cout << "Today's date is "; today.output( ); cout << "J. S. Bach's birthday is "; bach_birthday.output( ); if (equal(today, bach_birthday)) cout << "Happy Birthday Johann Sebastian!\n"; else cout << "Happy Unbirthday Johann Sebastian!\n"; return 0; } Function call: sends today and bach_birthday
Notice there is no scope resolution operator since it is not a member function of the class. //Function definition for equal bool equal(DayOfYear date1, DayOfYear date2) { return ( date1.get_month( ) == date2.get_month( ) && date1.get_day( ) == date2.get_day( ) ); } //Function definitions for DayOfYear class DayOfYear::DayOfYear(int the_month, int the_day){ month = the_month; day = the_day; } DayOfYear::DayOfYear( ){ month = 1; day = 1; } int DayOfYear::get_month( ){ return month; }
int DayOfYear::get_day( ){ return day; } //Uses iostream: void DayOfYear::input( ){ cout << "Enter the month as a number: "; cin >> month; cout << "Enter the day of the month: "; cin >> day; } //Uses iostream: void DayOfYear::output( ){ cout << "month = " << month << ", day = " << day << endl; }
The equal function must use accessor functions. bool equal(DayOfYear date1, DayOfYear date2){ return ( date1.get_month( ) == date2.get_month( ) && date1.get_day( ) == date2.get_day( ) ); } • Here the function is implemented as a “stand-alone” function. • The problem is, a stand-alone function, defined outside a class, must use accessor functions. • It is possible to allow ordinary functions to have direct access to data members (even though those members are private). • An ordinary function declared as a friend of the class gains the required access.
Friend Functions • An ordinary function declared as a friend of the class gains direct access to private data members without going through member functions. • The class grants friend status by declaring the function with the friend keyword. • When a friend function is defined, you do not use the class name and scope resolution operator as you do with members.
Declaring a function as a friend class DayOfYear Here equal is granted friend status { public: friend bool equal(DayOfYear date1, DayOfYear date2); //Precondition: date1 and date2 have values. //Returns true if date1 and date2 represent the same date; otherwise returns false. DayOfYear(int the_month, int the_day); DayOfYear( ); void input( ); void output( ); int get_month( ); int get_day( ); private: int month; int day; };
Friend vs Regular Function • If the function is listed as a friend in the class definition, the function definition looks like this… bool equal(DayOfYear date1, DayOfYear date2) { return ( date1.month == date2.month && date1.day == date2.day ) } • If the function is NOT listed as a friend in the class definition, the function definition would look like this… bool equal(DayOfYear date1, DayOfYear date2) { return ( date1.get_month( ) == date2.get_month( ) && date1.get_day( ) == date2.get_day( ) ); }
Review of Friend Functions • A friend function of a class is an ordinary (non-member) function that has access granted to private members of a that class. • To make a function a friend of a class • list that function prototype in the class with the keyword friend. • The prototype may be placed in either the public or the private section of the class; however by convention is often placed first before either. • A friend function is NOT a member function. • A friend function is defined and called the same way as any ordinary function. • You do not use the dot operator to call a friend function, and you do not use a class resolution operator in the definition of a friend function.
Consider this code fragment from a mainline function: DayOfYear today; //declaration of an instance of the class cout << “enter today’s date: \n”; today.input(); cout << “There are << (12 - today.get_month()) << “ months left in the year. \n”; • You cannot replace today.get_month() with today.month because month is a private data member. • The function get.month() is a public member function used to access the value stored in the private data member month. • Main does not have direct access because it is not listed as a friend.
Use both Member and Nonmember functions. • Members and friends of a class do similar services for a class. • To clarify whether a given task should be done by a friend or member, consider: • Use a member function if the task being performed by the function involves only one object. • Use a nonmember function if the task being performed involves more than one object. Example: The function equal involves two objects, so we make it a friend. bool equal(DayOfYear date1, DayOfYear date2){ return ( date1.month = = date2.month && date1.day = = date2.day ); } • Whether member or non-member is not always as simple as this rule suggests. • Clarity and readability is the cardinal rule for this issue.
The const Parameter Modifier • Call-by-value vs. call-by-reference • Call-by-value creates second copy of values • Call-by-value ensures function cannot change parameters • Call-by-reference more efficient for large objects such as classes • For classes use call-by-reference with keyword const • The const modifier allows you to pass a parameter by reference (saving overhead) but guarantees not to change the current value. • The compiler will emit error messages when you compile code that does change the parameter
The const Parameter Modifier Example: Money add(const Money& amount1, const Money& amount2); Here any code written in the implementation of the add function that might change amount1 or amount2 will be marked as an error.
Prototype and Header MUST agree • If you use the const parameter modifier in your prototype in your class, you MUST use the const modifier in exactly the same way in your definition, or you will get errors when you compile your code. Example: class SomeClass { public: void aFunc( const int & aVar, double & bVar); friend int compare(const Date & date1, const Date & date2); }; void SomeClass::aFunc(const int & aVar, double & bVar) { // whatever aFunc does } const in prototype must have const in function definition
Use const with member functions • Use const when member function does not change value of calling object Class SomeClass { void output(ostream & outifle) const; }; void SomeClass::output(ostream & outfile) const { // does output } int main(){ SomeClass ObjA; ObjA.output(outfile); ….. } function prototype function header in application, output function cannot change ObjA
What does const do in each of these cases? const int X = 17; class AClass { public: AClass( ); AClass(int); int aFunc( ) const; int bFunc(const AClass& obj1); private: int i; };
CRC • CRC (for Class, Responsibility, and Collaboration) cards • invented CRC cards in response to a need to document collaborative design decisions