Reputation: 25924
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?
Upvotes: 36
Views: 13963
Reputation: 1801
Another use for placing friend function definition inside a class is to implement the hidden friend idiom.
E.g., the following code from Argument dependent look-up and the hidden friend idiom by Rainer Grimm.
// hiddenFriend.cpp
#include <iostream>
class MyDistance{
public:
explicit MyDistance(double i):m(i){}
friend MyDistance operator+(const MyDistance& a, const MyDistance& b){ // (1)
return MyDistance(a.m + b.m);
}
friend MyDistance operator-(const MyDistance& a, const MyDistance& b){ // (2)
return MyDistance(a.m - b.m);
}
friend std::ostream& operator<<(std::ostream &out, const MyDistance& myDist){ // (3)
out << myDist.m << " m";
return out;
}
private:
double m;
};
int main() {
std::cout << '\n';
std::cout << "MyDistance(5.5) + MyDistance(5.5): " << MyDistance(5.5) + MyDistance(5.5) << '\n'; // (4)
std::cout << "MyDistance(5.5) - MyDistance(5.5): " << MyDistance(5.5) - MyDistance(5.5) << '\n'; // (5)
std::cout << '\n';
}
Since the scope of the friend functions is within the class in which they are defined, the correct operator+, operator- and operator<< are picked-up because of ADL.
This idiom is also very useful in the context of class templates to generate appropriate friend functions based on the template arguments.
Upvotes: 1
Reputation: 133577
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:
person
to int
so that <
can use it without accessing any private field.friend
of person
so that it can access x
in the right-hand side of the comparison.Upvotes: 4
Reputation: 2992
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>>
Upvotes: 15
Reputation: 5784
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.
Upvotes: 4
Reputation: 1745
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'
}
Upvotes: 7
Reputation: 29724
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.
Upvotes: 2