Thread: A treatise on friend is needed

  1. #1
    Registered User
    Join Date
    May 2010
    Posts
    178

    A treatise on friend is needed

    I sign reads "loss of encapsulation" and the accompanying lights and siren are indicating, at least in my head, that friendship is best for Humans but not always for classes.

    Can someone please expound this new year's day on why I should care about friendship in c++ as it relates to classes and member functions?

    Thank you

  2. #2
    Bored Programmer
    Join Date
    Jul 2009
    Location
    Tomball, TX
    Posts
    428
    Honestly I had never heard of the friend feature to c++ until tonight with Thames' post. I am definitely going to have to look it up and do some research on its usage.

    I am assuming you already read that thread? I believe grumpy and a few others spoke of some of the benifits and disadvantages of the friend feature.
    Virtual reality hello world http://www.rodneybrothers.com/vr/vrh...rld/index.html in html and javascript.
    Viewable with dodocase, google cardboard, OR, and other compatible VR gear.

  3. #3
    Registered User
    Join Date
    May 2010
    Posts
    178
    Quote Originally Posted by Lesshardtofind View Post
    Honestly I had never heard of the friend feature to c++ until tonight with Thames' post. I am definitely going to have to look it up and do some research on its usage.

    I am assuming you already read that thread? I believe grumpy and a few others spoke of some of the benifits and disadvantages of the friend feature.
    No, I have not read nor was I aware that a detailed post regarding friendship was around. I will have to check it out.

  4. #4
    Registered User
    Join Date
    Sep 2011
    Posts
    25
    The thread Lesshardtofind is referencing is over here, though at the time of this post the "when is friendship appropriate" discussion didnt really have much meat to it. As grumpy mentioned, the advantage of friendship is that you are given better control over which classes or functions may access sensitive data. Its also important to note that friendships arent always necessary and are very easily used inappropriately (which I feel is what std10093 was trying to say in the other thread).

    A bad example of friendship would be if you have a screensaver program with a Ball class, a Box class, and a Triangle class, with the potential to add more shapes later. Each class has data members that keep track of the object's position and velocity on the screen, and must be able to bounce off eachother. Friendship could be used here, making every class every other's friend, but is considered bad technique since you would be just as well to mark the data members public or create interfacing methods.

    A good example of friendship would be a banking program with an Account class (keeps track of the money in an account), an ATM class (manages the money in an account), and an AverageJoe class (people that use the ATM). You want the ATM to be able to check and alter the total held in Account, but you dont want AverageJoe to be able to do so. If you create interfacing methods in Account to return or change it, AverageJoe would also be able to use those methods. However, if you mark ATM or a member function as a friend, you have your solution.

    Hope that helps! If you need more reading, check out Friendship and inheritance - C++ Documentation. Happy holidays

  5. #5
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    If you haven't heard of friend or needed it very often, that's probably a good thing. If friendship is appropriate, your design wouldn't work without it. As with any way to grant access rights, it is about selecting the best, as in most restrictive, level of access.

    Let's take a closer look at the stream operator >> and operator << first. It is not all that hard to code an operator << in terms of normal "getter functions", but once you make "getter" functions, any other object can call those. This can be a drawback despite being completely safe: this exposes the implementation of the object, and the level of access could undermine your intentions. If you print an ID by calling "int getID() const;" you might otherwise not have a use for such a function, so a friend operator is better. You should see you have a similar problem with the operator >> being implemented in terms of "setter" functions. The example of ATMs and bank accounts has a similar conundrum: it is perfectly possible to write an account class that uses getters and setters, but it exposes the implementation. More importantly, it might be your intention that it is only possible to modify a bank account through an ATM, instead of just anywhere in the whole program. In each example use of friend, you are saying as the implementer of the class to the client: perform this action with this class using this friend method only, or perform these actions only with this friend class.

    That last sentence cannot be repeated enough times. A friend method or class is just another arm of your public interface, where other choices are too intrusive. "Exposing the implementation" may not seem like a big deal, but it can be, especially if you use a certain idiom.

    And the whole idea of "coupling" is just what it advertizes... in many cases, a specific design decision like using "friend" marries two things that used to have a wall of separation. I hope that clears up the other thread.
    Last edited by whiteflags; 01-02-2013 at 12:19 AM.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    These articles concentrate more on membership than friendship, but they should also give you some insight on the topic:
    How Non-Member Functions Improve Encapsulation by Scott Meyers
    GotW #84: Monoliths "Unstrung" by Herb Sutter
    The C++ Style Sweet Spot: Designing Simple Interfaces (inteview of Bjarne Stroustrup)
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    I'm not going to write a treatise on friend, but will make a few observations.

    1) Friendship is a design and implementation decision, not a decision about how a class (or instances of the class) will be used. By granting friendship, a class allows other entities (other classes, functions, even a member function of a class) direct access to its private and protected implementation details. It is therefore necessary to specify exactly what a friend is allowed to do as carefully as you would specify what member function would do.

    2) Anything that a class declares as a friend becomes part of the public interface of that class. There is no difference between a friend doing something it shouldn't with private data (or operations) versus the class' member function doing something it shouldn't with that same private data. Similarly, there is no difference between a friend doing something with protected data (or operations) and the class member functions, or member functions of derived classes, doing something they shouldn't with that protected data.

    3) This is completely different from inheritance. A derived class cannot access private members of a base class. Protected members of a base class do not become public members of a derived class.

    4) Used with care, friends actually support comparable or greater degrees of encapsulation than do member functions (as they are not members, they can be used to improve encapsulation). A function that returns a reference or pointer to a class' internal data actually provides less protection of that data than does a friend (unless that friend does the unfriendly - or over friendly, depending on your viewpoint - act of exposing a reference or pointer to the class' internal data).

    5) Friends do not replace any need for getter or setter functions. However, if some function (such as streaming operators) needs access to data for which there is no getter or setter, then that operation needs to be a friend. If it makes sense for the getters and setters to be public, then a function which can do its job completely by use of those getters and setters does not need to be a friend. With careful use of friends, a class does not need to expose getters or setters unless the designer or the class chooses to do so.

    6) Since friends, like public member functions are part of the public interface of a class, their implementation is also sensitive to changes of that class's private (and protected) implementation details. So, for example, if the private data of a class measures length in centimetres, then all friends and all member functions must be implemented with that in mind. If the implementation changes to store length in metres, all friends and all member functions must be updated accordingly. If those friends and member functions are consistent in how they expose length to code outside the class (eg they all provide lengths in inches) then code which uses those member functions or friends does not need to change.

    It would probably help if people understood that encapsulation is a measure of how sensitive code is to changes of class implementation. The smaller the number of functions that break when internal class representations change, the greater the encapsulation.
    Last edited by grumpy; 01-02-2013 at 01:20 AM.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by grumpy
    Used with care, friends actually support comparable or greater degrees of encapsulation than do member functions (as they are not members, they can be used to improve encapsulation).
    No, I would argue that they do not support greater degrees of encapsulation than do member functions: the fact that they are not members is not relevant here, since either way "the smaller the number of functions that break when internal class representations change, the greater the encapsulation".
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by laserlight View Post
    No, I would argue that they do not support greater degrees of encapsulation than do member functions: the fact that they are not members is not relevant here, since either way "the smaller the number of functions that break when internal class representations change, the greater the encapsulation".
    It depends on how much abstraction you're interested in. Access of class members by member functions tends to be more granular than access by friends, simply because it is often easier to get ones mind around an external function accessing multiple data members of a class (or even data belonging to multiple instances) than it is to get ones mind around a member function doing so.

    A single friend function that is exposed to multiple changes of internal representation represents a greater level of encapsulation than multiple getters/setters that each access one of the internal data elements. (Again assuming the measure of encapsulation is number of functions that must be updated when internal representations change - since it is rare for a change of internal representation to affect only one data member among several).
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by grumpy
    It depends on how much abstraction you're interested in. Access of class members by member functions tends to be more granular than access by friends, simply because it is often easier to get ones mind around an external function accessing multiple data members of a class (or even data belonging to multiple instances) than it is to get ones mind around a member function doing so.
    This observation does not show that "friends actually support comparable or greater degrees of encapsulation than do member functions". Rather, it is a practical point concerning the tendency of those who design classes with respect to these features.

    Quote Originally Posted by grumpy
    A single friend function that is exposed to multiple changes of internal representation represents a greater level of encapsulation than multiple getters/setters that each access one of the internal data elements.
    However, it does not represent a greater level of encapsulation than a rough equivalent single member function "that is exposed to multiple changes of internal representation". This is why I agree with "comparable", but not with "greater". If we're looking at a choice between making a function a member or a friend because it needs access to the internals, then I would say to prefer making it a member, unless there is a compelling reason to make it a friend (e.g., because the first parameter must be of a different type, or it is already a member of a different class).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by laserlight View Post
    This observation does not show that "friends actually support comparable or greater degrees of encapsulation than do member functions". Rather, it is a practical point concerning the tendency of those who design classes with respect to these features.
    Sure, although that tendency of those who design classes does have an effect on various measures - such as those related to sensitivity to change.

    Also, bear in mind that the probability of (A or B) is never less than the probability of A.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  12. #12
    Registered User
    Join Date
    Dec 2012
    Posts
    45
    Quote Originally Posted by Imanuel View Post
    [..] why I should care about friendship in c++ as it relates to classes and member functions?
    Suppose that you have to write your own STL-like container. The iterators might need to access the internals of the data structure. When you implement the ++ operator, for instance, you have two options:

    1) Provide, in the container class, a _public_ method, and have it called from the ++ operator of the iterator class.

    2) Declare, in the container class, that the iterator class is a friend. Then you can choose to access directly to the internals of the container from the iterator class, or use intermediate _private_ methods of the container.

    The second option is somehow cleaner, The clients (the users of your container) will have only one way to call each operation (++, --, etc.).

    Happy new year!

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by comocomocomo
    2) Declare, in the container class, that the iterator class is a friend. Then you can choose to access directly to the internals of the container from the iterator class, or use intermediate _private_ methods of the container.
    If the iterator class is declared within the container class, then it would have access to the private members of the container class even without being declared a friend since a nested class is permitted such access.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Registered User
    Join Date
    Dec 2012
    Posts
    45
    Quote Originally Posted by laserlight View Post
    If the iterator class is declared within the container class, then it would have access to the private members of the container class even without being declared a friend since a nested class is permitted such access.
    Very interesting! Well, that narrows my list of real-life, good 'friend' examples (from my own experience) to... zero ;-)

  15. #15
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by comocomocomo View Post
    Very interesting! Well, that narrows my list of real-life, good 'friend' examples (from my own experience) to... zero ;-)
    Well, overloading stream operators often need the declarations to be 'friendly'.
    I have seen that example in a lot of places, so I think it is not evil™.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Helping out a friend...
    By rhymewithnothin in forum C Programming
    Replies: 21
    Last Post: 09-15-2005, 08:59 PM
  2. for a friend
    By Ajsan in forum C++ Programming
    Replies: 4
    Last Post: 02-25-2004, 11:04 AM
  3. friend function and friend classes...usage question??
    By actionbasti in forum C++ Programming
    Replies: 2
    Last Post: 10-30-2003, 10:53 PM
  4. friend
    By laasunde in forum C++ Programming
    Replies: 3
    Last Post: 11-30-2002, 10:15 AM