Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Friend classes

  1. Dec 27, 2015 #1

    ChrisVer

    User Avatar
    Gold Member

    I know that this might seem a little stupid question, but I'd like to read some answers or maybe see some examples (better put as problems for my own practice)?
    I don't understand how the concept of friend classes is useful in programing.
    Classes, in my understanding, are supposed to be some kind of structures that allow you to create objects with certain attributes and methods on those objects. The attributes or methods can be private (accessed only from within the class) or public (accessed from outside the class), and recently I came across the protected but I am not sure how it really works yet but this is irrelevant.
    Then I learned that friend classes are able to access the private elements of its class.
    What is confusing me, is that I don't see the reason of making some elements of a class private if you want to access them in some other part of your code later on. Or define a friend class that you want to enter the private parts of your main class and modify them instead of doing that in your main class (this question may not receive an answer, since it's based on the contradiction arising between the concepts of friendship and encapsulation). Especially if you are building the code, I find the whole concept of friendship irrelevant (since there are ways to avoid it) and the code to be less readable to others (at least I can get confused reading through such a code).
    I would appreciate your answers. Also, do you have some examples that can make the concept of friendship clear and necessary? I would appreciate the examples as "problems" (to make me think about it) rather than a copy-paste of some code.
    Thanks.
     
  2. jcsd
  3. Dec 27, 2015 #2
    This is a common question. There is no contradiction between the concepts of friendship and encapsulation. https://isocpp.org/wiki/faq/friends#friends-and-encap

    Since you ask for an example as a problem to think about: in addition to the points in that FAQ, and the standard example of operator overloading, I invite you to consider using friends for unit testing.
     
  4. Dec 27, 2015 #3
    There are many features that you don't have to use. I don't recall ever having used a friend class or operator overloading. So, I wouldn't worry about it. Just be aware it exists. My guess is that you will never feel a need for them.
     
  5. Dec 28, 2015 #4

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    You didn't mention friend functions. Do you understand how they are useful?

    Friendship doesn't break encapsulation. It extends it, and under controllable circumstances. As a young adult, you may still have the key to your parent's house, but maybe not to their boat.

    To address the latter part of this question, one very common use of friend classes is in classes where all (or almost) all of the work is performed by a private data member of an opaque pointer type:
    Code (C):
    // File Foo.hpp

    #ifndef FOO_HPP
    #define FOO_HPP

    // Most of the functionality in class Foo is performed by class FooImplementation.
    // All we need here is a forward declaration of that class.
    class FooImplementation;

    class Foo {
    public:
        Foo();
        void do_something();
        void do_something_else(Foo& other);
    private:
        friend class FooImplementation;
        FooImplementation* impl;
    };

    #endif
    Code (C):
    // File FooImplementation.hpp

    #ifndef FOO_IMPLEMENTATION_HPP
    #define FOO_IMPLEMENTATION_HPP

    #include "foo.hpp"
    #include "foreign/object.hh"

    class FooImplementation {
    public:
        FooImplementation();
        void do_something();
        void do_something_else(Foo& other);
    private:
        foreign::object foreign_object;
    };

    #endif
    Code (C):
    // Foo.cpp

    #include "Foo.hpp"
    #include "FooImplementation.hpp"

    void Foo::do_something() {
        impl->do_something ();
    }

    void Foo::do_something_else (Foo& other) {
        impl->do_something_else (other);
    }
    Here, the private implementation walls off the #include "foreign/object.hh" that is needed in the definition of FooImplementation. That external header might in turn #include lots of other files. In modern C++, it's not uncommon to see a short file expand into tens or even hundreds of thousands once the preprocessor is done with that short file. The PIMPL design pattern acts as a compilation firewall that helps prevent the generation of those massive files.


    Another place where friendship is used widely is in operator overloading. Suppose you want to develop a linear algebra package. Because operators in C++ are boolean (e.g., a+b+c+d is implemented as ((a+b)+c)+d or a+(b+(c+d))), a naive implementation will most likely result in generation of temporaries. This has a number of downsides: Multiple traversals where one would do, and multiple calls to new and delete (which in turn call malloc and free), where only one temporary (or perhaps not even one) is needed. This overhead can be avoided by using expression templates to implement lazy evaluation. Those expression class templates oftentimes need to be friends of the matrix or vector classes so as to ultimately perform the computation.
     
  6. Dec 28, 2015 #5
    You haven't been programming very long have you? :P

    Friend classes are pretty useless if you design your code correctly. Every so often you want a class to be able to manipulate another one's private functions, but it's rare. The only example I can think of is a factory class, often you don't want to be able to use the new operator to create a new instance of a class, so you make all of the ctors private and use a factory class to create them. I usually put the factor method in the same class that it's trying to create, but sometimes I create factories that can return a number of different types of objects.

    However, there is one place where it's very very useful.
    Code (C):
    class foo {
    private:
        friend class UnitTest;  //You should certainly be asserting private members in a unit test
    };
     
  7. Dec 28, 2015 #6
    I guess not. Only twenty-five years.

    Please do not send me any more insults, if that's not too much to ask.
     
  8. Dec 28, 2015 #7
    I didn't mean to insult, I'm very surprised that someone with your experience have never needed operator overloading. Especially the assignment operator, which is normally coded in tandem with the copy constructor.
     
    Last edited: Dec 28, 2015
  9. Dec 28, 2015 #8

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    You haven't been programming very long have you? :P (Right back at ya!)

    Look at Boost and the C++ standard library before you say that. Both use friend classes quite extensively, particularly for the PIMPL idiom. Eigen and BLITZ++ use friend classes, too. Friend classes can be quite useful when used in the right context.

    This is one of those religious wars in modern programming. There are many who highly debate that "you should certainly be asserting private members in a unit test". While some say you certainly should unit test protected and private members (in which case you need to break encapsulation), others say you certainly should not.
     
  10. Dec 28, 2015 #9

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    I doubt @Hornbeim was thinking of the assignment operator when he wrote "I don't recall ever having used a friend class or operator overloading." Properly overloading the assignment operator is basic rule of three stuff (or with c++11 and beyond, rule of five stuff). I suspect he was instead thinking of the other 49 overloadable operators in C++. How many times have you found a need to overload the comma operator?

    I've written a few simple classes where I've overloaded operator+ et al, but I'm more likely to be using some carefully designed and very well-tested package that has done all the hard work of making sure that those overloaded arithmetic operators are well-behaved. It's easy to get it wrong and create overloads that behave poorly.
     
  11. Dec 28, 2015 #10
    True, I've never used the comma operator. +=, ++, ==, =... are very common though, especially if you have containers with iterators.

    @ChrisVer As for protected methods, these are the same as private methods, except they are also accessible by child classes. A private member or method is not usable by any object that inherits from your base class, this is useful for hiding weird internals that the child classes should not be interacting with.

    I'm actually on the side that unit tests should not be friends with anything, I just mentioned it as a common use. I actually do something completely different (-D private=public at compile time,) but that's equally controversial.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook




Similar Discussions: Friend classes
  1. Wrapper Classes (Replies: 3)

  2. Class conundrum (Replies: 4)

  3. Classes and objects (Replies: 6)

  4. Pointers and classes (Replies: 1)

Loading...