When should you use 'friend' in C++?

前端 未结 30 1609
孤街浪徒
孤街浪徒 2020-11-22 10:12

I have been reading through the C++ FAQ and was curious about the friend declaration. I personally have never used it, however I am interested in exploring the language.

相关标签:
30条回答
  • 2020-11-22 10:53

    Friend comes handy when you are building a container and you want to implement an iterator for that class.

    0 讨论(0)
  • 2020-11-22 10:53

    Friends are also useful for callbacks. You could implement callbacks as static methods

    class MyFoo
    {
    private:
        static void callback(void * data, void * clientData);
        void localCallback();
        ...
    };
    

    where callback calls localCallback internally, and the clientData has your instance in it. In my opinion,

    or...

    class MyFoo
    {
        friend void callback(void * data, void * callData);
        void localCallback();
    }
    

    What this allows is for the friend to be a defined purely in the cpp as a c-style function, and not clutter up the class.

    Similarly, a pattern I've seen very often is to put all the really private members of a class into another class, which is declared in the header, defined in the cpp, and friended. This allows the coder to hide a lot of the complexity and internal working of the class from the user of the header.

    In the header:

    class MyFooPrivate;
    class MyFoo
    {
        friend class MyFooPrivate;
    public:
        MyFoo();
        // Public stuff
    private:
        MyFooPrivate _private;
        // Other private members as needed
    };
    

    In the cpp,

    class MyFooPrivate
    {
    public:
       MyFoo *owner;
       // Your complexity here
    };
    
    MyFoo::MyFoo()
    {
        this->_private->owner = this;
    }
    

    It becomes easier to hide things that the downstream needn't see this way.

    0 讨论(0)
  • 2020-11-22 10:54

    I'm only using the friend-keyword to unittest protected functions. Some will say that you shouldn't test protected functionality. I, however, find this very useful tool when adding new functionality.

    However, I don't use the keyword in directly in the class declarations, instead I use a nifty template-hack to achive this:

    template<typename T>
    class FriendIdentity {
    public:
      typedef T me;
    };
    
    /**
     * A class to get access to protected stuff in unittests. Don't use
     * directly, use friendMe() instead.
     */
    template<class ToFriend, typename ParentClass>
    class Friender: public ParentClass
    {
    public:
      Friender() {}
      virtual ~Friender() {}
    private:
    // MSVC != GCC
    #ifdef _MSC_VER
      friend ToFriend;
    #else
      friend class FriendIdentity<ToFriend>::me;
    #endif
    };
    
    /**
     * Gives access to protected variables/functions in unittests.
     * Usage: <code>friendMe(this, someprotectedobject).someProtectedMethod();</code>
     */
    template<typename Tester, typename ParentClass>
    Friender<Tester, ParentClass> & 
    friendMe(Tester * me, ParentClass & instance)
    {
        return (Friender<Tester, ParentClass> &)(instance);
    }
    

    This enables me to do the following:

    friendMe(this, someClassInstance).someProtectedFunction();
    

    Works on GCC and MSVC atleast.

    0 讨论(0)
  • 2020-11-22 10:54

    To do TDD many times I've used 'friend' keyword in C++.
    Can a friend know everything about me?

    No, its only a one way friendship :`(

    0 讨论(0)
  • 2020-11-22 10:56

    The creator of C++ says that isn't broking any encapsulation principle, and I will quote him:

    Does "friend" violate encapsulation? No. It does not. "Friend" is an explicit mechanism for granting access, just like membership. You cannot (in a standard conforming program) grant yourself access to a class without modifying its source.

    Is more than clear...

    0 讨论(0)
  • 2020-11-22 10:58

    When implementing tree algorithms for class, the framework code the prof gave us had the tree class as a friend of the node class.

    It doesn't really do any good, other than let you access a member variable without using a setting function.

    0 讨论(0)
提交回复
热议问题