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

前端 未结 30 1530
孤街浪徒
孤街浪徒 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:37

    @roo: Encapsulation is not broken here because the class itself dictates who can access its private members. Encapsulation would only be broken if this could be caused from outside the class, e.g. if your operator << would proclaim “I'm a friend of class foo.”

    friend replaces use of public, not use of private!

    Actually, the C++ FAQ answers this already.

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

    One specific instance where I use friend is when creating Singleton classes. The friend keyword lets me create an accessor function, which is more concise than always having a "GetInstance()" method on the class.

    /////////////////////////
    // Header file
    class MySingleton
    {
    private:
        // Private c-tor for Singleton pattern
        MySingleton() {}
    
        friend MySingleton& GetMySingleton();
    }
    
    // Accessor function - less verbose than having a "GetInstance()"
    //   static function on the class
    MySingleton& GetMySingleton();
    
    
    /////////////////////////
    // Implementation file
    MySingleton& GetMySingleton()
    {
        static MySingleton theInstance;
        return theInstance;
    }
    
    0 讨论(0)
  • 2020-11-22 10:39

    edit: Reading the faq a bit longer I like the idea of the << >> operator overloading and adding as a friend of those classes, however I am not sure how this doesn't break encapsulation

    How would it break encapsulation?

    You break encapsulation when you allow unrestricted access to a data member. Consider the following classes:

    class c1 {
    public:
      int x;
    };
    
    class c2 {
    public:
      int foo();
    private:
      int x;
    };
    
    class c3 {
      friend int foo();
    private:
      int x;
    };
    

    c1 is obviously not encapsulated. Anyone can read and modify x in it. We have no way to enforce any kind of access control.

    c2 is obviously encapsulated. There is no public access to x. All you can do is call the foo function, which performs some meaningful operation on the class.

    c3? Is that less encapsulated? Does it allow unrestricted access to x? Does it allow unknown functions access?

    No. It allows precisely one function to access the private members of the class. Just like c2 did. And just like c2, the one function which has access is not "some random, unknown function", but "the function listed in the class definition". Just like c2, we can see, just by looking at the class definitions, a complete list of who has access.

    So how exactly is this less encapsulated? The same amount of code has access to the private members of the class. And everyone who has access is listed in the class definition.

    friend does not break encapsulation. It makes some Java people programmers feel uncomfortable, because when they say "OOP", they actually mean "Java". When they say "Encapsulation", they don't mean "private members must be protected from arbitrary accesses", but "a Java class where the only functions able to access private members, are class members", even though this is complete nonsense for several reasons.

    First, as already shown, it is too restricting. There's no reason why friend methods shouldn't be allowed to do the same.

    Second, it is not restrictive enough. Consider a fourth class:

    class c4 {
    public:
      int getx();
      void setx(int x);
    private:
      int x;
    };
    

    This, according to aforesaid Java mentality, is perfectly encapsulated. And yet, it allows absolutely anyone to read and modify x. How does that even make sense? (hint: It doesn't)

    Bottom line: Encapsulation is about being able to control which functions can access private members. It is not about precisely where the definitions of these functions are located.

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

    In C++ "friend" keyword is useful in Operator overloading and Making Bridge.

    1.) Friend keyword in operator overloading :
    Example for operator overloading is: Let say we have a class "Point" that has two float variable
    "x"(for x-coordinate) and "y"(for y-coordinate). Now we have to overload "<<"(extraction operator) such that if we call "cout << pointobj" then it will print x and y coordinate (where pointobj is an object of class Point). To do this we have two option:

       1.Overload "operator <<()" function in "ostream" class.
       2.Overload "operator<<()" function in "Point" class.
    Now First option is not good because if we need to overload again this operator for some different class then we have to again make change in "ostream" class.
    That's why second is best option. Now compiler can call "operator <<()" function:

       1.Using ostream object cout.As: cout.operator<<(Pointobj) (form ostream class).
    2.Call without an object.As: operator<<(cout, Pointobj) (from Point class).

    Beacause we have implemented overloading in Point class. So to call this function without an object we have to add"friend" keyword because we can call a friend function without an object. Now function declaration will be As:
    "friend ostream &operator<<(ostream &cout, Point &pointobj);"

    2.) Friend keyword in making bridge :
    Suppose we have to make a function in which we have to access private member of two or more classes ( generally termed as "bridge" ) . How to do this:
    To access private member of a class it should be member of that class. Now to access private member of other class every class should declare that function as a friend function. For example : Suppose there are two class A and B. A function "funcBridge()" want to access private member of both classes. Then both class should declare "funcBridge()" as:
    friend return_type funcBridge(A &a_obj, B & b_obj);

    I think this would help to understand friend keyword.

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

    You may use friendship when different classes (not inheriting one from the other) are using private or protected members of the other class.

    Typical use cases of friend functions are operations that are conducted between two different classes accessing private or protected members of both.

    from http://www.cplusplus.com/doc/tutorial/inheritance/ .

    You can see this example where non-member method accesses the private members of a class. This method has to be declared in this very class as a friend of the class.

    // friend functions
    #include <iostream>
    using namespace std;
    
    class Rectangle {
        int width, height;
      public:
        Rectangle() {}
        Rectangle (int x, int y) : width(x), height(y) {}
        int area() {return width * height;}
        friend Rectangle duplicate (const Rectangle&);
    };
    
    Rectangle duplicate (const Rectangle& param)
    {
      Rectangle res;
      res.width = param.width*2;
      res.height = param.height*2;
      return res;
    }
    
    int main () {
      Rectangle foo;
      Rectangle bar (2,3);
      foo = duplicate (bar);
      cout << foo.area() << '\n';
      return 0;
    }
    
    0 讨论(0)
  • 2020-11-22 10:43

    I found handy place to use friend access: Unittest of private functions.

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