A friend function of a class is defined outside that class's scope, yet has the right to access the non-public (and public) members of the class. Standalone functions or entire classes may be declared to be friends of another class.
Using friend functions can enhance performance. This section presents a mechanical example of how a friend function works. Later in the book, friend functions are used to overload operators for use with class objects (Chapter 11) and to create iterator classes (Chapter 21). Objects of an iterator class can successively select items or perform an operation on items in a container class object (see Section 10.9). Objects of container classes can store items. Using friends is often appropriate when a member function cannot be used for certain operations, as we will see in Chapter 11.
To declare a function as a friend of a class, precede the function prototype in the class definition with keyword friend. To declare all member functions of class ClassTwo as friends of class ClassOne, place a declaration of the form
friend class ClassTwo;
in the definition of class ClassOne.
Software Engineering Observation 10.7
Even though the prototypes for friend functions appear in the class definition, friends are not member functions. |
Software Engineering Observation 10.8
Member access notions of private, protected and public are not relevant to friend declarations, so friend declarations can be placed anywhere in a class definition. |
Good Programming Practice 10.1
Place all friendship declarations first inside the class definition's body and do not precede them with any access specifier. |
Friendship is granted, not takeni.e., for class B to be a friend of class A, class A must explicitly declare that class B is its friend. Also, the friendship relation is neither symmetric nor transitive; i.e., if class A is a friend of class B, and class B is a friend of class C, you cannot infer that class B is a friend of class A (again, friendship is not symmetric), that class C is a friend of class B (also because friendship is not symmetric), or that class A is a friend of class C (friendship is not transitive).
Software Engineering Observation 10.9
Some people in the OOP community feel that "friendship" corrupts information hiding and weakens the value of the object-oriented design approach. In this text, we identify several examples of the responsible use of friendship. |
Modifying a Class's private Data With a Friend Function
Figure 10.15 is a mechanical example in which we define friend function setX to set the private data member x of class Count. Note that the friend declaration (line 10) appears first (by convention) in the class definition, even before public member functions are declared. Again, this friend declaration can appear anywhere in the class.
Figure 10.15. Friends can access private members of a class.
(This item is displayed on pages 542 - 543 in the print version)
1 // Fig. 10.15: fig10_15.cpp 2 // Friends can access private members of a class. 3 #include 4 using std::cout; 5 using std::endl; 6 7 // Count class definition 8 class Count 9 { 10 friend void setX( Count &, int ); // friend declaration 11 public: 12 // constructor 13 Count() 14 : x( 0 ) // initialize x to 0 15 { 16 // empty body 17 } // end constructor Count 18 19 // output x 20 void print() const 21 { 22 cout << x << endl; 23 } // end function print 24 private: 25 int x; // data member 26 }; // end class Count 27 28 // function setX can modify private data of Count 29 // because setX is declared as a friend of Count (line 10) 30 void setX( Count &c, int val ) 31 { 32 c.x = val; // allowed because setX is a friend of Count 33 } // end function setX 34 35 int main() 36 { 37 Count counter; // create Count object 38 39 cout << "counter.x after instantiation: "; 40 counter.print(); 41 42 setX( counter, 8 ); // set x using a friend function 43 cout << "counter.x after call to setX friend function: "; 44 counter.print(); 45 return 0; 46 } // end main
|
Function setX (lines 3033) is a C-style, stand-alone functionit is not a member function of class Count. For this reason, when setX is invoked for object counter, line 42 passes counter as an argument to setX rather than using a handle (such as the name of the object) to call the function, as in
counter.setX( 8 );
As we mentioned, Fig. 10.15 is a mechanical example of using the friend construct. It would normally be appropriate to define function setX as a member function of class Count. It would also normally be appropriate to separate the program of Fig. 10.15 into three files:
Erroneously Attempting to Modify a private Member with a Non-friend Function
The program of Fig. 10.16 demonstrates the error messages produced by the compiler when non-friend function cannotSetX (lines 2932) is called to modify private data member x.
Figure 10.16. Non-friend/nonmember functions cannot access private members.
(This item is displayed on pages 544 - 545 in the print version)
1 // Fig. 10.16: fig10_16.cpp 2 // Non-friend/non-member functions cannot access private data of a class. 3 #include 4 using std::cout; 5 using std::endl; 6 7 // Count class definition (note that there is no friendship declaration) 8 class Count 9 { 10 public: 11 // constructor 12 Count() 13 : x( 0 ) // initialize x to 0 14 { 15 // empty body 16 } // end constructor Count 17 18 // output x 19 void print() const 20 { 21 cout << x << endl; 22 } // end function print 23 private: 24 int x; // data member 25 }; // end class Count 26 27 // function cannotSetX tries to modify private data of Count, 28 // but cannot because the function is not a friend of Count 29 void cannotSetX( Count &c, int val ) 30 { 31 c.x = val; // ERROR: cannot access private member in Count 32 } // end function cannotSetX 33 34 int main() 35 { 36 Count counter; // create Count object 37 38 cannotSetX( counter, 3 ); // cannotSetX is not a friend 39 return 0; 40 } // end main Borland C++ command-line compiler error message:
Microsoft Visual C++.NET compiler error messages:
GNU C++ compiler error messages:
|
It is possible to specify overloaded functions as friends of a class. Each overloaded function intended to be a friend must be explicitly declared in the class definition as a friend of the class.
Introduction to Computers, the Internet and World Wide Web
Introduction to C++ Programming
Introduction to Classes and Objects
Control Statements: Part 1
Control Statements: Part 2
Functions and an Introduction to Recursion
Arrays and Vectors
Pointers and Pointer-Based Strings
Classes: A Deeper Look, Part 1
Classes: A Deeper Look, Part 2
Operator Overloading; String and Array Objects
Object-Oriented Programming: Inheritance
Object-Oriented Programming: Polymorphism
Templates
Stream Input/Output
Exception Handling
File Processing
Class string and String Stream Processing
Web Programming
Searching and Sorting
Data Structures
Bits, Characters, C-Strings and structs
Standard Template Library (STL)
Other Topics
Appendix A. Operator Precedence and Associativity Chart
Appendix B. ASCII Character Set
Appendix C. Fundamental Types
Appendix D. Number Systems
Appendix E. C Legacy Code Topics
Appendix F. Preprocessor
Appendix G. ATM Case Study Code
Appendix H. UML 2: Additional Diagram Types
Appendix I. C++ Internet and Web Resources
Appendix J. Introduction to XHTML
Appendix K. XHTML Special Characters
Appendix L. Using the Visual Studio .NET Debugger
Appendix M. Using the GNU C++ Debugger
Bibliography