14

Possible Duplicate:
When should you use 'friend' in C++?

I have come to a stumbling block because of lack of documentation on friend classes. Most books just explain it briefly, e.g an excerpt from C++: the Complete Reference:

Friend Classes are seldom used. They are supported to allow certain special case situations to be handled.

And frankly, I have never seen a friend class in any good code made by an experienced C++ programmer. So , here is my list of problems.

  1. Do Inherited Classes have the same friends as there base classes? e.g, if I declare class foo as a friend of class base, will class der (derived from base) also have foo as a friend?

  2. What are the special case situations when a friend class should be used?

  3. I am making a winapi wrapper in which I want to make class WinHandle a friend of class Widget (to access some protected members). Is it recommended? Or should I just access them using the traditional Get/Set functions?

ApprenticeHacker
  • 21,351
  • 27
  • 103
  • 153

4 Answers4

37

Friend is used for granting selective access, just like the protected access specifier. It's also hard to come up with proper use case where use of protected is really useful.

In general, friend classes are useful in designs where there is intentional strong coupling: you need to have a special relationship between two classes. More specifically, one class needs access to another classes's internals and you don't want to grant access to everyone by using the public access specifier.

The rule of thumb: If public is too weak and private is too strong, you need some form of selected access: either protected or friend (the package access specifier in Java serves the same kind of role).

Example design

For instance, I once wrote a simple stopwatch class where I wanted to have the native stopwatch resolution to be hidden, yet to let the user query the elapsed time with a single method and the units to be specified as some sort of variable (to be selected by user preferences, say). Rather than, have say elapsedTimeInSeconds(), elapsedTimeInMinutes(), etc. methods, I wanted to have something like elapsedTime(Unit::seconds). To achive both of these goals, I can't make the native resolution public nor private, so I came up with the following design.

Implementation overview

class StopWatch;

// Enumeration-style class.  Copy constructor and assignment operator lets
// client grab copies of the prototype instances returned by static methods.
class Unit
{
friend class StopWatch;
    double myFactor;
    Unit ( double factor ) : myFactor(factor) {}
    static const Unit native () { return Unit(1.0); }
public:
        // native resolution happens to be 1 millisecond for this implementation.
    static const Unit millisecond () { return native(); }

        // compute everything else mostly independently of the native resolution.
    static const Unit second () { return Unit(1000.0 / millisecond().myFactor); }
    static const Unit minute () { return Unit(60.0 / second().myFactor); }
};

class StopWatch
{
    NativeTimeType myStart;
    // compute delta using `NativeNow()` and cast to
    // double representing multiple of native units.
    double elapsed () const;
public:
    StopWatch () : myStart(NativeNow()) {}
    void reset () { myStart = NativeNow(); }
    double elapsed ( const Unit& unit ) const { return elapsed()*unit.myFactor; }
};

As you can see, this design achieves both goals:

  1. native resolution is never exposed
  2. desired time unit can be stored, etc.

Discussion

I really like this design because the original implementation stored the multiple of native time units and performed a division to compute the elapsed time. After someone complained the division was too slow, I changed the Unit class to cache the dividend, making the elapsed() method (a little) faster.

In general, you should strive for strong cohesion and weak coupling. This is why friend is so little used, it is recommended to reduce coupling between classes. However, there are situations where strong coupling gives better encapsulation. In those cases, you probably need a friend.

André Caron
  • 44,541
  • 12
  • 67
  • 125
  • Awesome answer! I am beginning to understand the importance of good design. (upvote). – ApprenticeHacker Jul 16 '11 at 15:47
  • Perfect answer. I like the stopwatch design. I have just spent 10 minutes trying to pick it apart but nothing is pick-able. I like the fact that you mention coupling. You could mention that tight coupling unto itslef is not a bad thing (when done correctly) and that friendship is a mechanism for documenting the coupling. – Martin York Jul 16 '11 at 15:55
  • @Martin: I like that last part of your comment "friendship is a mechanism for documenting coupling". I'll be using that! – André Caron Jul 16 '11 at 16:04
  • @Martin: looking at this again, I noticed I missed the most important part of the implementation. There *was* no friend declaration in the example code! Just added it. – André Caron Jul 16 '11 at 16:20
  • @André Caron: +1, Nice explanation and an Excellent example. – Alok Save Jul 17 '11 at 08:19
  • Sorry, but where is the definition of NativeNow()? – Lewis Levin May 13 '23 at 22:14
6

Do Inherited Classes have the same friends as there base classes? e.g if i declare class foo as a friend of class base, will class der (derived from base) also have foo as a friend?

The rule with friend keyword is:
Friendship attribute is not inherited.
So No friend of base class will not be friend of Derived class.


What are the special case situations when a friend class should be used?

Frankly, (IMHO) using friend classes is mostly done to achieve some things for rather ease of usage. If a software is designed taking in to consideration all the requirememtens then there would practically no need of friend classes. Important to note perfect designs hardly exist and if they do they are very difficult to acheive.

An example case which needs friend class:
Sometimes there may be a need for a tester class(which is not part of the release software) to have access to internals of classes to examine and log certain specific results/diagnostics. It makes sense to use friend class in such a scenario for ease of usage and preventing overhead of design.


I am making a winapi wrapper in which I want to make class WinHandle a friend of class Widget (to access some protected members). Is it recommended? Or should I just access them using the traditional Get/Set functions?

I would stick to the traditional setter/getter. I rather avoid using friend where I can get working through usual OOP construct. Perhaps, I am rather paranoid about using friend because if my classes change/expand in future I perceive the non inheritance attribute of friend causing me problems.


EDIT:
The comments from @Martin, and the excellent answer from @André Caron, provide a whole new perspective about usage of friendship, that I had not encountered before & hence not accounted for in the answer above. I am going to leave this answer as is, because it helped me learn a new perspective & hopefully it will help learn folks with a similar outlook.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • I didnt do it. I don't know why, but somebody is randomly downvoting every good answer. (An upvote to even things up) – ApprenticeHacker Jul 16 '11 at 15:20
  • Out of curiosity, How do you add those horizontal lines to your answer? – ApprenticeHacker Jul 16 '11 at 15:40
  • The use of friend classes for testing is [strongly debated](http://stackoverflow.com/questions/1149244/using-a-friend-class-vs-adding-accessors-for-unit-testing-in-c). – André Caron Jul 16 '11 at 15:43
  • 1
    -1: For getter/Setter. That is the worst way to build you classes it ruins encapsulation. Also your opinion on why is misleading at best at worst wrong. – Martin York Jul 16 '11 at 15:51
  • @Martin: I do not contest the downvote, though why is the the opinion of why misleading? Atleast i may learn through your wise words. – Alok Save Jul 16 '11 at 15:58
  • 1
    @Als: I completely disagree with this:`using friend classes is mostly done to achieve some things for rather ease of usage`.It is misleading to newcomers that we use friendship to break encapsulation just to make our life easier.We use friendship when their is a tight coupling between two entities that we want to reflect in the design. The use of the friend declaration in effect documents the tight coupling in addition to providing access. Friendship is done when two entities are designed together; the friend expanding the public interface of the class in a way that the class can't do alone. – Martin York Jul 16 '11 at 16:29
  • 1
    I would consider making the stream operator << and >> friends a good design option. As you are expanding the public interface of the class in a way the class can not do itself. These operators usually need to be friends so that they can efficiently stream the private data into/out of the object into the stream. Also making them friends publicly documents that that their is a tight coupling between these objects. (they are also usually the first functions you write for a class and are as such done at the same time). – Martin York Jul 16 '11 at 16:33
  • 1
    If you change the internal structure of a class. You must also update evreything that is coupled. The list of friends makes this easy all the tightly coupled objects. – Martin York Jul 16 '11 at 16:34
  • @Martin: Thanks, That opens me up to a new perspective about using `friend`ship. – Alok Save Jul 17 '11 at 08:13
1

friend usually accounts for where you would normally use one single class, but you have to use more because they have different life-times or instance counts, for example. friendship is not transferred or inherited or transitive.

Get/Set is quite terrible, although better than it could be. friend allows you to limit the damage to just one class. Usually you will make an intermediary class which is friended.

class MyHandleIntermediary;
class MyHandle {
    friend class MyHandleIntermediary;
private:
    HANDLE GetHandle() const;
};
class MyWidget;
class MyHandleIntermediary {
    friend class MyWidget;
    static HANDLE GetHandle(const MyWidget& ref) {
        return ref.GetHandle();
    }
};
class MyWidget {
    // Can only access GetHandle() and public
};

This allows you to change the accessibility of friendship on a per-member level and ensures that the extra accessibility is documented in a single place.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • (+1). I understand. But why are Get/Set functions terrible? – ApprenticeHacker Jul 16 '11 at 15:16
  • @burningprodigy: Because they usually show that you haven't actually thought about your class design and are mindlessly exposing elements because you can. Get/Set only originated to be read back by automated reflection APIs, or used where binary compatibility was necessary (e.g. WinAPI), and never used in in-source code. – Puppy Jul 16 '11 at 15:26
  • I see (Maybe that is why the WinAPI is so ugly). But what are the alternatives. like should i just declare the member I want to use Get/Set with as **public**? – ApprenticeHacker Jul 16 '11 at 15:31
  • 1
    @burningprodigy: Yes. The advantage of using `friend` this way is that only one class has access to them, improving the encapsulation. If you make them public to anyone, then you've increased the visibility. – Puppy Jul 16 '11 at 15:40
  • @DeadMG: you forget about another valid `get`/`set` use case. Sometime s it is useful for the `get` or `set` to return a transformation of the actual member's value. – Evan Teran Jul 16 '11 at 15:41
  • @Evan Teran: You will notice that I still used a get in my code sample. I added `usually` for a reason, and that reason is that they definitely are more encapsulated than public member variables, just most of the time, YAGNI. – Puppy Jul 16 '11 at 15:44
  • @Evan Teran: That is hardly ever required. get/set is a usually weak crutch for bad design. If an object needs to transform then it should know how to do it itself not an external entity. – Martin York Jul 16 '11 at 16:01
0

One of the cases where I applied the "friend classes", is where one class is composed or referenced by other (objects) classes, and the composing objects, require access to the internals of the main class.

enum MyDBTableButtonBarButtonKind {
  GoFirst,
  GoPrior,
  GoNext,
  GoLast
}

class MyDBTableButtonBarButtonWidget;

class MyDBTableButtonBarWidget {

  friend class MyDBTableButtonBarButtonWidget;

// friend access method:
protected:
  void GoFirst();
  void GoPrior();
  void GoNext();
  void GoLast();

  void DoAction(MyDBTableButtonBarButtonKind Kind);
};

class MyDBTableButtonBarButtonWidget {

private:

  MyDBTableButtonBarWidget* Toolbar;

public:

  MyDBTableButtonBarButtonWidget(MyDBTableButtonBarWidget* AButtonBar) {
    this ButtonBar = AButtonBar;
  }

  MyDBTableButtonBarButtonKind Kind; 
public:
  virtual void Click() { Buttonbar->DoAction(this Kind); }; 
};

void MyDBTableButtonBarWidget::DoAction(MyDBTableButtonBarButtonKind Kind)
{
  switch (Kind)
  {
     case MyDBTableButtonBarButtonKind::GoFirst:
       this.GoFirst();
     break;

     case MyDBTableButtonBarButtonKind::GoLast:
       this.GoLast();
     break;
  }
}

In this example, there is a widget control that is a bar composed of buttons, the buttonbar is referenced to a D.B. table, and has several buttons for a specific action, like select the first record of the table, edit, move to the next.

In order to do so, each button class has friend access to private & protected methods, of the given control. As previous answer in this post, usually friend classes act a single class, decomposed in several smaller classes.

It's not a finished example, its only a general idea.

umlcat
  • 4,091
  • 3
  • 19
  • 29