- Next chapter
- Previous chapter
- Table of contents

# Chapter 13: More about friends

> We're always interested in getting feedback. E-mail us if you like this guide, if you think that important material is omitted, if you encounter errors in the code examples or in the documentation, if you find any typos, or generally just if you feel like e-mailing. Mail to Frank Brokken or use an e-mail form. Please state the concerned document version, found in the title.

Let's return to `friend`s once more. In section 4.6 the possibility of declaring a function or class as a friend of a class was discussed. At the end of that section, we mentioned

- Friendship, when applied to program design, is an escape mechanism which circumvents the principle of data hiding. Using friend classes should therefore be minimized to those cases where it is absolutely essential.

- If friends are used, realize that the implementation of classes or functions that are friends to other classes become implementation dependent on these classes. In the above example: once the internal organization of the data of the class `A` changes, all its friends must be recompiled (and possibly modified) as well.

- As a rule of thumb: don't use friend functions or classes.

In our opinion, there are indeed very few reasons for using the `friend` keyword. It violates the principle of data hiding, and makes the maintenance of a class dependent on another class.

Nonetheless, it might be worthwhile to look at some examples in which the `friend` keyword can be used profitably. Having seen such examples, the decision about whether or not to use `friend`s might be based on a somewhat more solid foundation than on a plain rule of thumb.

At the onset, we remark that in our programming projects we never found any convincing reason to resort to `friend`s. Having thus made our position clear, let's consider a situation where it would be nice for an existing class to have access to another class.

Such a situation might occur when we would like to give an old class access to a class developed later in history.

However, while developing the older class, it was not yet known that the newer class would be developed later in time. E.g., the older class is distributed in the runtime-library of a compiler, and the newer class is a class developed by us.

Consequently, no provisions were offered in the older class to access the information in the newer class.

Consider the following situation. Within the `C++` I/O-library the extraction `>>` and insertion `<<` operators may be used to extract from and to insert into a stream.

These operators can be given data of several types: `int, double, char *`, etc.. Now assume that we develop a class `String`. Objects of the `class String` can be given a string, and `String` objects can also produce other `String` objects.

While it is possible to use the insertion operator to write the string that is stored in the object to a stream, it is not possible to use the extraction operator, as illustrated by the following piece of code:

        #include <iostream>

        class String
        {
            public:
                // ...
                void set(char const *s);
                char const *get() const;
            private:
                char
                    *str;
        };

        void f()
        {
            String
                str;

            str.set("hello world");
                // Assign a value. Can't use
                // cin >> str.set() or
                // a similar construction

            cout << str.get() << endl;
                // this is ok.
        }

Actually, the use of the insertion operator in combination with the `String` class is also a bit of a kludge: it isn't the `String` object that is inserted into the stream, but rather a string produced by one of its members.

Below we'll discuss a method to allow the insertion and extraction of `String` objects, based on the use of the `friend` keyword.

## 13.1: Inserting String objects into streams

Assume that we would like to be able to insert `String` objects into streams, rather than derivatives of `String` objects, like `char const *`'s. If we would be able to write `String` objects into streams, we could be using code comparable to

        int main()
        {
            String
                str("Hello world");

            cout << "The string is: '" << str << "'" << endl;
            return (0);
        }

Analogously, with the extraction operator, we would like to be able to write code comparable to the next example:

        int main()
        {
            String
                str;

            cout << "Enter your string: ";

            cin >> str;

            cout << "Got: '" << str << "'" << endl;

            return (0);
        }

In this situation we would not have to rely on the availability of a particular member (like `char const *String::get()`), and we would be able to fill a `String` object directly via the extraction operator, rather than via an intermediate variable of a type understood by the `cin` stream.

Even more central to the concept of object oriented programming: we would be able to ignore the functionality of the `String` class in combination with `iostream` objects: our objective is, after all, to insert the information in the `String` object into the `cout` stream, and not to call a particular function to do so.

Once we're able to focus our attention on the object, rather than on its member functions, the above piece of code remains valid, no matter what internal organization the `String` object has.

## 13.2: An initial solution

Consider the following overloaded operator `>>`, to be used as an extraction operator with a `String` object:

        istream &String::operator>>(istream &is)
        {
            char
                buffer[500];
                // assume this buffer to be
                // large enough.

            is >> buffer;      // extraction

            delete str;     // free this->str
                            // memory

                            // assign new value
            str = strdupnew(buffer);

            return (is);    // return is-reference
        }

The extraction operator can now be used with `String` objects. Unfortunately, this implementation produces awkward code. The extraction operator is part of the `String` class, so its left operand must be a `String` object.

As the left operand must be a `String` object, we're now forced to use weird-looking code like the following, which can only partially be compiled. The numbered statements are annotated next.

        void fun()
        {
            String
                s;

            s >> cin;           // (1)

            int x;

            s >> (cin >> x);    // (2)

            cin >> x >> s;      // (3)
        }

1. In this statement `s` is the left-hand operator, and `cin` the right-hand, consequently, this statement represents extraction from a `cin` object into a `String` object.

2. In this statement parentheses are needed to indicate the proper ordering of the sub-expressions: first `cin >> x` is executed, producing an `istream &`, which is then used as a right-hand operand with the `extraction` to `s`.

3. This statement is what we want, but it doesn't compile: the `istream`'s overloaded operator `>>` doesn't know how to extract information into `String` objects.

## 13.3: Friend-functions

The last statement of the previous example is in fact what we want. How can we accomplish the syntactical (and semantical) correctness of that last statement?

A solution is to overload the global `>>` operator to accept a left-operand of the `istream &` type, and a right operand of the `String &` type, returning an `istream &`. Its prototype is, therefore:

`istream &operator>>(istream &is, String &destination);`

To implement this function, the implementation given for the overloaded extraction operator of the `String` class can't simply be copied, since the private datamember `str` is accessed there. A small (and perfectly legal) modification would be to access the `String`'s information via a `char const *String::get() const` member, but this would again generate a dependency on the `String::get()` function, which we would like to avoid.

However, the need for overloading the extraction operator arose strictly in the context of the `String` class, and is in fact depending on the existence of that class. In this situation the overloading of the operator could be considered an extension to the `String` class, rather than to the `iostream` class.

Next, since we consider the overloading of the `>>` operator in the context of the `String` class an extension of the `String` class, we feel safe to allow that function access to the private members of a `String` object, instead of forcing the `operator>>()` function to assign the data members of the `String` object through the `String`'s member functions.

Access to the private data members of the `String` object is granted by declaring the `operator>>()` function to be a `friend` of the `String` class:

        #include <iostream>

        class String
        {
            friend istream &operator>>(istream &is,
                                       String &destination);
            public:
                // ...
            private:
                char
                    *str;
        };

        istream &operator>>(istream &is, String &destination)
        {
            char
                buffer[500];

            is >> buffer;                  // extraction

            delete destination.str;     // free old 'str' memory

            destination.str = strdupnew(buffer);
                                        // assign new value

            return (is);                // return istream-reference
        }

        void fun()
        {
            String
                s;

            cin >> s;   // application

            int
                x;

            cin >> x >> s;
                        // extraction order is now
                        // as expected
        }

Note that nothing in the implementation of the `operator>>()` function suggests that it's a friend of the `String` class. The compiler detects this only from the `String` interface, where the `operator>>()` function is declared as a friend.

### 13.3.1: Preventing the friend-keyword

Now that we've seen that it's possible to define an overloaded `operator>>()` function for the `String` class, it's hopefully clear that there is only very little reason to declare it as a friend of the `class String`, assuming that the proper memberfunctions of the class are available.

On the other hand, declaring the `operator>>()` as a friend function isn't that much of a problem, as the `operator>>()` function can very well be interpreted as a true member function of the `class String`, although, due to a syntactical peculiarity, it cannot be defined as such.

To illustrate the possibility of overloading the `>>` operator for the `istream` and `String` combination, we present here the version which does not have to be declared as a `friend` in the `String` class interface. This implementation assumes that the class `String` has an overloaded operator `=`, accepting as r-value a `char const *`:

        istream &operator>>(istream &lvalue, String &rvalue)
        {
            char
                buffer[500];

            lvalue >> buffer;      // extraction

            rvalue = buffer;       // assignment

            return (lvalue);    // return istream-reference
        }

No big deal, isn't it? After all, whether or not to use `friend` functions might purely be a matter of taste. As yet, we haven't come across a situation where `friend` functions are truly needed.

## 13.4: Friend classes

Situations may arise in which two classes doing closely related tasks are developed together.

For example, a window application can define a class `Window` to contain the information of a particular window, and a class `Screen` shadowing the `Window` objects for those windows that are actually visible on the screen.

Assuming that the window-contents of a `Window` or `Screen` object are accessible through a `char *win` pointer, of `unsigned size` characters, an overloaded operator `!=` can be defined in one (or both) classes to compare the contents of a `Screen` and `Window` object immediately. Objects of the two classes may then be compared directly, as in the following code fragment:

        void fun()
        {
            Screen
                s;
            Window
                w;

            // ... actions on s and w ...

            if (w != s)         // refresh the screen
                w.refresh(s);   // if w != s
        }

It is likely that the overloaded operator `!=` and other member functions of `w` (like `refresh()`) will benefit from direct access to the data of a `Screen` object. In this case the class `Screen` may declare the class `Window` as a friend class, thus allowing `Window`'s member functions to access the private members of its objects.

A (partial) implementation of this situation is:

        class Window;       // forward declaration
        class Screen
        {
            friend class Window;    // Window's object may
                                    // access Screen's
                                    // private members
            public:
                // ...
            private:
                // ...
                char
                    *win;
                unsigned
                    size;
        };

        // =============================================
        // now in Window's context:

        int Window::operator!=(Screen const &s)
        {
            return
            (
                s.size != size      // accessing Screen's
                ||                  // private members
                !memcmp(win, s.win, size)
            );
        };

It is also possible to declare classes to be each other's friends, or to declare a global function to be a friend in multiple classes. While there may be situations where this is a useful thing to do, it is important to realize that these multiple friendships actually violate the principle of encapsulation.

In the example we've been giving earlier for single `friend` functions, the implementation of such functions can be placed in the same directory as the actual member functions of the class declaring the function to be its friend. Such functions can very well be considered part of the class implementation, being somewhat `eccentric` member functions. Those functions will normally be inspected automatically when the implementation of the data of the class is changed.

However, when a class itself is declared as a friend of another class, things become a little more complex. If the sources of classes are kept and maintained in different directories, it is not clear where the code of `Window::operator!=()` should be stored, as this function accesses private members of both the class `Window` and `Screen`. Consequently caution should be exercized when these situations arise.

In our opinion it's probably best to avoid friend classes, as they violate of the central principle of encapsulation.

- Next chapter
- Previous chapter
- Table of contents