friend Functions and friend Classes

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;
 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
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
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 
35 int main()
36 {
37 Count counter; // create Count object
39 cout << "counter.x after instantiation: ";
40 counter.print();
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
 counter.x after instantiation: 0
 counter.x after call to setX friend function: 8

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:

  1. A header file (e.g., Count.h) containing the Count class definition, which in turn contains the prototype of friend function setX
  2. An implementation file (e.g., Count.cpp) containing the definitions of class Count's member functions and the definition of friend function setX
  3. A test program (e.g., fig10_15.cpp) with main

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;
 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
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
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 
34 int main()
35 {
36 Count counter; // create Count object
38 cannotSetX( counter, 3 ); // cannotSetX is not a friend
39 return 0;
40 } // end main

Borland C++ command-line compiler error message:

 Error E2247 Fig10_16/fig10_16.cpp 31: 'Count::x' is not accessible in
 function cannotSetX(Count &,int)

Microsoft Visual C++.NET compiler error messages:

 C:cpphtp5_examplesch10Fig10_16fig10_16.cpp(31) : error C2248: 'Count::x'
 : cannot access private member declared in class 'Count'
 C:cpphtp5_examplesch10Fig10_16fig10_16.cpp(24) : see declaration
 of 'Count::x'
 C:cpphtp5_examplesch10Fig10_16fig10_16.cpp(9) : see declaration
 of 'Count'

GNU C++ compiler error messages:

 fig10_16.cpp:24: error: `int Count::x' is private
 fig10_16.cpp:31: error: within this context

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.

C++ How to Program
C++ How to Program (5th Edition)
ISBN: 0131857576
EAN: 2147483647
Year: 2004
Pages: 627
Simiral book on Amazon © 2008-2017.
If you may any questions please contact us: