FAQ 19.01 What is a friend?

graphics/new_icon.gif

A friend is an entity to which a class grants access authority.

Friends can be functions, other classes, or individual member functions of other classes. Friend classes are used when two or more classes are designed to work together and need access to each other's implementation in ways that the rest of the world shouldn't be allowed to have. In other words, they help keep private things private. For instance, it may be desirable for class DatabaseCursor to have more privilege to the internals of class Database than main() has.

In the early days of OO, people had all sorts of strange ideas. Some people thought that the class was the fundamental unit that had to be encapsulated and concluded that friendship was evil. Experience has shown that some abstractions require more than one class, and that the abstraction needs the encapsulation barriers more than the component classes. As long as they are used properly, friends enhance the encapsulation of abstractions.

Friend classes normally imply that one abstraction (a database with multiple cursors, for example) is implemented using several distinct classes (Database and DatabaseCursor). Using several classes to implement one abstraction is especially useful when the various classes have different lifetimes or different cardinalities. For example, it is likely that there are an arbitrary number of DatabaseCursor objects for any given Database object.

 #include <stdexcept> #include <string> using namespace std; class BTree { /*...*/ }; class Cache { /*...*/ }; class DatabaseCursor; class Database { public:   unsigned numRecords() const throw(); protected:   friend DatabaseCursor;   // Grant access to DatabaseCursor   BTree btree_;   Cache cache_; }; class DatabaseCursor { public:   string getCurrentRecord() const throw(out_of_range);   void   changeCurrentRecord(const string& record)                                         throw(out_of_range);   void   goToNextRecord() throw(out_of_range); protected:   Database* db_;                                     <-- 1                                                      <-- 2 }; 

(1) The Database to which this cursor object is attached

(2) Pointers into the BTree and/or Cache go here

It would be a bad idea to force class Database and class DatabaseCursor into one class by moving the member functions of DatabaseCursor into class Database (so we would now have Database::getCurrentRecord()). This would impose a one-cursor-per-database policy and would cause Database to manage both the data and a current position within that data.

The UML diagram for this friendship relationship follows.

graphics/19fig01.gif



C++ FAQs
C Programming FAQs: Frequently Asked Questions
ISBN: 0201845199
EAN: 2147483647
Year: 2005
Pages: 566
Authors: Steve Summit

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