Section 12.5. Friends


12.5. Friends

In some cases, it is convenient to let specific nonmember functions access the private members of a class while still preventing general access. For example, over-loaded operators, such as the input or output operators, often need access to the private data members of a class. For reasons we'll see in Chapter 14 these operators might not be members of the class. Yet, even if they are not members of the class, they are "part of the interface" to the class.

The friend mechanism allows a class to grant access to its nonpublic members to specified functions or classes. A friend declaration begins with the keyword friend. It may appear only within a class definition. Friend declarations may appear anywhere in the class: Friends are not members of the class granting friendship, and so they are not affected by the access control of the section in which they are declared.

Ordinarily it is a good idea to group friend declarations together either at the beginning or end of the class definition.



Friendship: An Example

Imagine that in addition to the Screen class we had a window manager that manages a group of Screens on a given display. That class logically might need access to the internal data of the Screen objects it manages. Assuming that Window_Mgr is the name of the window-management class, Screen could let Window_Mgr access its members as follows:

      class Screen {          // Window_Mgr members can access private parts of class Screen          friend class Window_Mgr;          // ...restofthe Screen class      }; 

The members of Window_Mgr can refer directly to the private members of Screen. For example, Window_Mgr might have a function to relocate a Screen:

      Window_Mgr&      Window_Mgr::relocate(Screen::index r, Screen::index c,                           Screen& s)      {           // ok to refer to height and width           s.height += r;           s.width += c;           return *this;      } 

In absence of the friend declaration, this code would be in error: It would not be allowed to use the height and width members of its parameter named s. Because Screen grants friendship to Window_Mgr, all the members of Screen are accessible to the functions in Window_Mgr.

A friend may be an ordinary, nonmember function, a member function of another previously defined class, or an entire class. In making a class a friend, all the member functions of the friend class are given access to the nonpublic members of the class granting friendship.

Making Another Class' Member Function a Friend

Instead of making the entire Window_Mgr class a friend, Screen could have specified that only the relocate member was allowed access:

      class Screen {          // Window_Mgrmust be defined before class Screen          friend Window_Mgr&              Window_Mgr::relocate(Window_Mgr::index,                                   Window_Mgr::index,                                   Screen&);          // ...restofthe Screen class      }; 

When we declare a member function to be a friend, the name of the function must be qualified by the name of the class of which it is a member.

Friend Declarations and Scope

Interdependencies among friend declarations and the definitions of the friends can require some care in order to structure the classes correctly. In the previous example, class Window_Mgr must have been defined. Otherwise, class Screen could not name a Window_Mgr function as a friend. However, the relocate function itself can't be defined until class Screen has been definedafter all, it was made a friend in order to access the members of class Screen.

More generally, to make a member function a friend, the class containing that member must have been defined. On the other hand, a class or nonmember function need not have been declared to be made a friend.

A friend declaration introduces the named class or nonmember function into the surrounding scope. Moreover, a friend function may be defined inside the class. The scope of the function is exported to the scope enclosing the class definition.



Class names and functions (definitions or declarations) introduced in a friend can be used as if they had been previously declared:

      class X {          friend class Y;          friend void f() { /* ok to define friend function in the class body */ }      };      class Z {          Y *ymem; // ok: declaration for class Y introduced by friend in X          void g() { return ::f(); } // ok: declaration of f introduced by X      }; 

Overloaded Functions and Friendship

A class must declare as a friend each function in a set of overloaded functions that it wishes to make a friend:

      // overloaded storeOn functions      extern std::ostream& storeOn(std::ostream &, Screen &);      extern BitMap& storeOn(BitMap &, Screen &);      class Screen {          // ostream version of storeOn may access private parts of Screen objects          friend std::ostream& storeOn(std::ostream &, Screen &);          // ...      }; 

Class Screen makes the version of storeOn that takes an ostream& its friend. The version that takes a BitMap& has no special access to Screen.

Exercises Section 12.5

Exercise 12.32:

What is a friend function? A friend class?

Exercise 12.33:

When are friends useful? Discuss the pros and cons of using friends.

Exercise 12.34:

Define a nonmember function that adds two Sales_item objects.

Exercise 12.35:

Define a nonmember function that reads an istream and stores what it reads into a Sales_item.




C++ Primer
C Primer Plus (5th Edition)
ISBN: 0672326965
EAN: 2147483647
Year: 2006
Pages: 223
Authors: Stephen Prata

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net