Why is it possible to place friend function definitions inside of a class definition?

10,832

Solution 1

Is it not supposed for a friend function to be explicitly defined outside of a class ?

Friend functions can be defined (given a function body) inside class declarations. These functions are inline functions, and like member inline functions they behave as though they were defined immediately after all class members have been seen but before the class scope is closed (the end of the class declaration). Friend functions that are defined inside class declarations are in the scope of the enclosing class. quote

Is it only OK with some operators such as < operator or is it applicable to all operators?

It is best to try to avoid friend functions since they are opposite to what you are trying to do using a private class scope and mainly "hide" the variables. If all your functions are friend functions then what is the use of having private variables?

Still, there are some common operators which are often declared as friend functions, those are operator<< and operator>>

Solution 2

Because an operator needs to know details of the right-hand side of the expression in which is used, if it must access private data of the type which resides on that side, it needs to be friend with that class.

If you are trying to compare an int with a person, like in your example, choices are two:

  • you provide an implicit conversion from person to int so that < can use it without accessing any private field.
  • or you declare the operator as friend of person so that it can access x in the right-hand side of the comparison.

Solution 3

If you are creating a header-only class (which makes deployment vastly easier) then defining a friend function within the class is the only way to go since definitions can only appear in a single translation unit. The normal technique of include guards doesn't work since that only handles things like recursive inclusion.

This can be a big deal if you are trying to write standards-conformant code. For example, to implement the RandomNumberEngine named requirement from the C++ normative standard, it is necessary to provide operator<<. This has to be a friend to take a std::ostream& object as its first parameter (otherwise it will look like a normal, single parameter member function operator overload). Ordinarily the friend declaration would go in the class definition and and the function definition in a separate .cpp source file. But if you want a header-only implementation, it must be defined in the class to avoid multiple definition errors.

Solution 4

As Jack mentioned friend functions are required in places where access to private data is needed. There is also another purpose. This is related to types of inheritance. Only derived class and its friends can convert pointer to a private base to a derived type. So you might sometimes want to make some function a friend of derived class to allow this inside function body.

Solution 5

Alexandru Barbarosie answer is correct. It means that we can declare a friend function, which is not a member function, within a class. This can be nice to organize the code. I think an example can help to understand it in case it isn't clear.

#include <iostream>

class A {
    public:
        A(int val) : val(val) {}
        // The following isn't a member function, it is a friend 
        // function declared inside the class and it has file scope
        friend void draw (A &a) {
            std::cout << "val: " << a.val << "\n";
        }
    private:
        int val;
};

int main() {
    A a(5);
    draw(a); // outputs "val: 5"
    //A::draw(a); // Error: 'draw' is not a member of 'A'
}
Share:
10,832
Hossein
Author by

Hossein

For the love of God, do not downvote new comers! help them kindly so they can feel a apart of this community!

Updated on June 03, 2022

Comments

  • Hossein
    Hossein almost 2 years

    Is it not supposed for a friend function to be explicitly defined outside of a class ?
    If so why can i declare a friend function inside a class definition just like any member function ?
    What is this ?
    Is it only OK with some operators such as < operator or is it applicable to all operators?
    If it is applicable to all of them, Is there any disadvantage for doing this ?
    Should it be avoided? If so why ?

    class person 
    {
    public:
        bool operator<(int num)
        {
            return  x < num ? true : false ;
        }
        bool operator<(person& p)
        {
            return  x < p.x ? true : false ;
        }
    
        friend bool operator<(int num, person &p)
        {
            return  p.x < num ? true : false ;
        }
    
        void setX(int num)
        {
            x = num;
        }
    
    private:
        int x;
    
    
    };
    

    Update:
    I am not asking for choosing non-member operator overloading or member operator overloading.
    What i want to know is that :
    Why we are permitted to move the definition of friend methods inside our class definition?.
    Is it not violating any things? If it is not, Why would we have friends in first place?
    We could simply define overloads as member functions ( I know the limitations of member functions ) But i am saying knowing this, Why isn't compiler complaining that I haven't defined friend function outside a class definition since it doesn't need to be inside of it (because of the class parameter it has) So why are we allowed to define a friend function inside a class definition?

  • Nicola Musatti
    Nicola Musatti almost 11 years
    That would still be possible if only the friend declaration was inside the class definition, with the friend function definition kept outside of it.
  • Hossein
    Hossein almost 11 years
    Thanks, But i didn't why we use friends, I asked why we are permitted to move the definition of friend methods inside our class definition. Is it not violating any things? If it is not, Why would we have friends in first place, We could simply define overloads as member functions ( I know the limitations of member functions ) but i am saying knowing this , why isn't compiler complaining that i haven't defined friend function outside a class definition since it doesnt need to be inside of it (because of the class parameter it has)
  • Jack
    Jack almost 11 years
  • Hossein
    Hossein almost 11 years
    Thank you very much :) I am not trying to declare all of my needed functions as friends, I was curios to know why a friend function (which is solely used for operating overloading and nothing else) can be defined inside a class and why it is permitted
  • Alexandru Barbarosie
    Alexandru Barbarosie almost 11 years
    @Hossein the quote I gave you doesn't atually say "why it is permited" but explains why "it is not not permited".
  • juanchopanza
    juanchopanza almost 11 years
    @Hossein obviously it is not "violating any things". Otherwise you couldn't even ask the question, because it wouldn't compile.
  • Hossein
    Hossein almost 11 years
    by violating i meant any thing such as good practice or the likes
  • Hossein
    Hossein almost 11 years
    i know , but the part "Friend functions can be defined inside class declarations" , says we are premitted to do so, i understand that friend functions are not an answer for everything as you have also clearly mentioned , when i was saying that , i meant the quoted section which kinda cleared parts of my question
  • Felix Dombek
    Felix Dombek over 5 years
    They are "in file scope"? Shouldn't they be inserted into the surrounding scope, be it file, namespace, function, class?
  • HolyBlackCat
    HolyBlackCat over 4 years
    "defining a friend function within the class is the only way to go" One could also use inline functions.
  • David G
    David G over 4 years
    @HolyBlackCat true, up to a point. However I'm not happy about doing this since inlines with non-static linkage do not need to be the same across translation units, and that's just asking for trouble. For an operator, it makes sense to keep the definition as closely associated with its class as possible.