This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
When should you use 'friend' in C++?
There is a detailed explanation here, but I would like to know what is the practical use of Friend function.
How I can decide when I should go with a friend function rather than a member function?
In most cases, friend declarations are a code-smell since it breaks encapsulation.
Developers often use friend for a quick-fix to a problem. However a good starting design or some refactoring (more often more than less) exclude the necessity for it.
EDIT:
Even in #Darhuuk's example, a friend declaration is not needed. You can have getters for the specific fields you want to print.
You would use a friend when the function needs to be a non-member, but also needs access to class members.
Common examples where you need a non-member function are:
An API that requires non-member functions; for example, boost::intrusive_ptr requires that you implement intrusive_add_ref() and intrusive_release() as non-member functions.
Overloading a binary operator where your type need to be the right-hand operand; for example operator<<(ostream&, my_type const &).
Overloading a binary operator where you want the left-hand side to be convertible to your type; for example, if your class is constructible from int, then 5 + my_type will work if you define a non-member operator+(my_type const&, my_type const&);, but not if you define a member my_type::operator+(my_type const &) const;.
Whether any of these needs to be friends depends on whether they can do their job using the class's public interface; for example, you could add a public print(ostream&) member that operator<< could use, and a public operator+= member that operator+ could use.
As an example of implementing operator+ in terms of operator+=:
my_type & my_type::operator+=(my_type const & rhs)
{
// do addition here
return *this;
}
// The first operand is passed by value, giving a modifiable copy
my_type operator+(my_type lhs, my_type const & rhs)
{
return lhs += rhs;
}
The simplest use case would probably be when overloading the stream output operator for a custom class.
For example, take a look at the following code (shamelessly copied from here). In this case the use of friend allows the non-class method to access the private fields of class, thus preventing the need to code several get methods (which otherwise you might not even want to create).
#include <iostream>
#include <cstring>
using namespace std;
class MyClass {
// now private
char name[80];
int areacode;
int prefix;
int num;
public:
MyClass(char *n, int a, int p, int nm)
{
strcpy(name, n);
areacode = a;
prefix = p;
num = nm;
}
friend ostream &operator<<(ostream &stream, MyClass o);
};
ostream &operator<<(ostream &stream, MyClass o)
{
stream << o.name << " ";
stream << "(" << o.areacode << ") ";
stream << o.prefix << "-" << o.num << "\n";
return stream;
}
int main() {
MyClass a("T", 1, 5, 1);
MyClass b("A", 3, 5, 5);
MyClass c("T", 2, 5, 9);
cout << a << b << c;
return 0;
}
Related
This question already has answers here:
What are the basic rules and idioms for operator overloading?
(8 answers)
Closed 3 years ago.
According to Can't Overload operator<< as member function
When overloaded as a member function, a << b is interpreted as
a.operator<<(b), so it only takes one explicit parameter (with this as
a hidden parameter).
Since this requires that the overload be part of the class used as the
left-hand operand, it's not useful with normal ostreams and such. It
would require that your overload be part of the ostream class, not
part of your class. Since you're not allowed to modify ostream class,
you can't do that. That leaves only the global overload as an
alternative.
I know that for example:
friend std::ostream& operator<< (std::ostream &out, const Obj &obj);
acts like a function that takes an object of ostream and some object that you are trying to print and then returns an ostream object.
But I don't understand how doing cout << obj will call this function.
Wouldn't cout << obj do something like cout.operator<<(obj), which is exactly what we don't want? So why does it actually call the function? And why does it allow the return value to go back to cout?
EDIT:
I had read over What are the basic rules and idioms for operator overloading? previously and it states
"A binary infix operator #, applied to the objects x and y, is called
either as operator#(x,y) or as x.operator#(y).4"
which provides some further clarity, but I don't see how it answers my question.
That's exactly what the answer you quote says, although it doesn't do so very well.
An operator overload can be a member, or a non-member.
For example, anOstream << aT can be resolved with a ostream& ostream::operator<<(T) (or similar) or with a free function ostream& operator<<(ostream&, T). Either of those can be called. That's just how it is. That's what the standard says.
Since we can't add things to ostream, the latter is how we go about it (though, for your own types, it would be pretty much up to you).
Notice how I chose a return type of ostream& for those examples; that's how "the return value goes back to cout": the left-hand operand is simply returned back by reference.
The compiler would call cout.operator<<(obj) if it was present but if it isn't it will look for a compatible global function.
e.g. Below it will call the member function. But if that is commented out it will call the global function.
#include <iostream>
class Ostr;
class Obj {
public:
void print(Ostr& os) const;
};
class Ostr {
public:
Ostr& operator<<(const Obj& obj){
std::cout << "member";
obj.print(*this);
return *this;
}
Ostr& operator<<(const char* obj){
std::cout << obj;
return *this;
}
};
void Obj::print(Ostr& os) const {
os << "Obj";
}
template<class T>
auto operator<<(Ostr& os, const T& t) -> decltype(t.print(os), os) {
os << "global";
t.print(os);
return os;
}
int main() {
Obj obj;
Ostr ostr;
ostr << obj;
return 0;
}
It is often overloaded as a friend function of the class. Is there any way it can be overloaded as a member function?
Is there any way it can be overloaded as a member function?
Let's say if you have a class Foo and you want to use:
Foo foo;
std::cout << foo;
No, it cannot.
A member function overload works only if the first argument is an object of the class. In the case of stream insertion operators, the first argument is a stream, not an object of the class.
If you want to use:
Foo foo;
foo << std::cout;
Yes, it can be defined as a member function.
A non-member function and a virtual member function can be combined to good effect when used in a situation where derived classes are involved.
struct Shape
{
// Member function that can be overridden by derived classes.
virtual std::ostream& operator<<(std::ostream& os) const = 0;
};
// Non-member function that makes use of member functions.
std::ostream& operator<<(std::ostream& os, Shape const& shape)
{
return shape << os;
}
struct Rectangle : public Shape
{
virtual std::ostream& operator<<(std::ostream& os) const
{
// Do the need full to stream a Rectangle.
// ...
return os;
}
};
struct Ellipse : public Shape
{
virtual std::ostream& operator<<(std::ostream& os) const
{
// Do the need full to stream an Ellipse.
// ...
return os;
}
};
Usage:
Rectangle r;
Ellipse e;
std::cout << r << std::endl;
std::cout << e << std::endl;
If you wanted to badly enough, you could use a member function overload, but it's directly contrary to convention, so doing it would lead to confusion. It would also prevent chaining extraction/insertion operators, and wouldn't work for reading/writing primitive types.
The reason behind this is that invoking an operator overloaded as a member function means that x << y; is interpreted as x.operator<<(y);, so the overloaded operator has to be a member of the left operand, not the right. It's possible to do that (iostreams include such overloads for some types), but it's essentially impossible to extend (all such overloads have to be part of the iostream object when it's the left operand).
If you want to overload it as a member of the object to be read/written, you need to put the object being read/written as the left operand. This means insertion would go from left to right instead of right to left. To have at least some chance of maintaining sanity, you'd almost certainly want to use >> for insertion, and << for extraction:
class my_class {
int x;
public:
bool operator<<(std::istream &is) {
// Note the reversal here. That's because we're defining this
// for a `my_class` on the left, and an iostream on the right,
// but the existing `>>` and `<<` use the reverse of that (iostream
// on the left).
is >> x;
return is.good();
}
bool operator>>(std::ostream &os) {
os << x;
return os.good();
}
};
my_class a;
a >> std::cout;
a << std::cin;
Note: I'm providing this answer only to point out that it's technically possible to do this, and show how. If you were starting over with a clean slate and you were really set on using member functions, I can see where you might conceivably choose this method--but even then, it's open to a lot of question.
In particular (as noted above) this would not support chaining. Since the insertion and extraction are done as member functions of the left operand, it also means it would only work for user-defined types, not any primitive types (int, short, long, float, double, bool, etc.)
Bottom line: if you want to badly enough, you can get it to work to a limited degree under limited circumstances--but neither well (no chaining) nor universally (no primitive types).
Is there any way it can be overloaded as a member function?
No. The signature of the function prevents this option.
// Binary operator where the stream object is left of '<<' and the object
// instance is right of '<<'
std::ostream& operator<<(std::ostream& lhs, const Foo& rhs)
For illustration here's a binary operator+ as a free function:
class Foo
{
};
Foo operator+(const Foo& lhs, const Foo& rhs)
{
// an appropriate implementation
}
int main()
{
Foo f1;
Foo f2;
// Uses the free function
Foo result = f1 + f2;
return 0;
}
However implemented as a member function it looks like this:
class Foo
{
public:
Foo operator+(const Foo& other) const
{
// an appropriate implementation
}
};
int main()
{
Foo f1;
Foo f2;
// The calling sequence is the same as before however 'f1' is logically
// the same as 'lhs' in the free function implementation example (i.e.,
// the first type in the binary operator must be the class type when
// implemented as a member function)
Foo result = f1 + f2;
return 0;
}
Given the operator+ member function example it is easier to see why the std::ostream& operator<<(std::ostream& lhs, const Foo& rhs) free function cannot be converted to an equivalent member function. Because 'lhs' would need to be the same type as std::ostream but this is only possible when implementing that class whereas in this example the Foo class is being implemented.
int i=0;
std::cout << i;
1, The non-member overload(two arguments, one being ostream& the other being type of operand, say int) is defined in std namespace. So if using namespace std; is not present, there's no way I see that the non-member overload can be called.
2, If instead, the member operator(member of ostream; one argument, being the type of operand, say int) function << of ostream is called, I'd expect something like: std::cout.operator<< i; --- isn't this rediculous?
So, what on earth is the relation between the two?
Question extended: if I want to overload the insertion operator so that std::cout << my_obj; works(assume my_obj is the instance of a user-defined type, MyType), should I do
a) ostream& operator<< (ostream& os, MyType obj); in the namespace of MyType
or
b) in MyType:
class MyType
{
...
ostream& operator<< (MyType);
};
does option b) ever work? Does it even make sense(I remember seeing it somewhere ...)? What's the relation between option a) & b)?
EDIT MAR 27
Upon the request from ecatmur, here're two overloads that have the same signature but in different namespaces. Using gcc 4.9.2: http://melpon.org/wandbox/
#include <iostream>
namespace MyNameSpace
{
class MyType
{};
// signature can be found here: http://www.cplusplus.com/reference/ostream/ostream/operator-free/
std::ostream& operator<<(std::ostream& out, char ch)
{
out << "std is doomed\n";
return out;
}
std::ostream& operator<<(std::ostream& out, MyType t)
{
out << "std is super doomed\n";
return out;
}
}
int main()
{
MyNameSpace::MyType t;
std::cout << t; // ... super doomed; ADL is working as intended.
std::cout << 't'; // t; this proves that when there're two operator overloads with the same signature but in different namespaces, there're no compilation errors. gcc defaults to the std one.
return 0;
}
The non-member overloads you're thinking of are those for character data and those for std::string etc.; they're available via argument-dependent lookup. You can indeed write std::cout.operator<<(i) for types where ostream has a member operator<<.
For your own types you're thinking of a (non-member) friend operator<<, which can be particularly useful for template classes (the Barton-Nackman trick) or for those where the operator<< accesses data not available via accessors:
class MyType
{
...
friend std::ostream& operator<< (std::ostream&, MyType obj) { ... }
};
Your proposed signature would allow you to write my_obj << my_obj, which is unlikely to make much sense.
I'm working on some homework and receiving the strangest error. Hoping you can help. I am getting this error:
Cannot access private member in class
Note: I am obviously not done writing this but I try to test for errors as I go. Thanks so much for any input you have!
// Amanda
// SoccerPlayer.cpp : main project file.
// October 6, 2012
/* a. Design a SoccerPlayer class that includes three integer fields: a player's jersey number,
number of goals, and number of assists. Overload extraction and insertion operators for the class.
b. Include an operation>() function for the class. One SoccerPlayer is considered greater
than another if the sum of goals plus assists is greater.
c. Create an array of 11 SoccerPlayers, then use the > operator to find the player who has the
greatest goals plus assists.*/
#include "stdafx.h"
#include<conio.h>
#include<iostream>
#include<string>
class SoccerPlayer
{
friend std::ostream operator<<(std::ostream, SoccerPlayer&);
// friend std::istream operator>>(std::istream, SoccerPlayer&);
private:
int jerseyNum;
int numGoals;
int numAssists;
public:
SoccerPlayer(int, int, int);
};
SoccerPlayer::SoccerPlayer(int jersey, int goal, int assist)
{
jerseyNum = jersey;
numGoals = goal;
numAssists = assist;
}
std::ostream operator<<(std::ostream player, SoccerPlayer& aPlayer)
{
player << "Jersey #" << aPlayer.jerseyNum <<
" Number of Goals " << aPlayer.numGoals <<
" Number of Assists " << aPlayer.numAssists;
return player ;
};
int main()
{
return 0;
}
You want to pass and return the streams by reference: you can't copy IOStream objects. Also, in case of the write, you probably want to pass a SoccerPlayer const&. With these changes you code should compiler (although there is also an excess semicolon after the definition of the output operator).
That is, you output operator should be declared as
std::ostream& operator<< (std::ostream&, SockerPlayer const&)
(both in its definition and the friend declaration).
std::ostream is not copyable. You need to pass a reference, and return a reference:
friend std::ostream& operator<<(std::ostream&, const SoccerPlayer&);
....
std::ostream& operator<<(std::ostream& player, const SoccerPlayer& aPlayer) { /* as before */ }
Note also that there is no reason not to pass the SoccerPlayer as a const reference.
On a note completely unrelated to the error, you should prefer to use the constructor initialization list instead of assigning values to data members in the constructor body:
SoccerPlayer::SoccerPlayer(int jersey, int goal, int assist)
: jerseyNum(jersey), numGoal(goal), numAssists(assist) {}
You should send the reference of ostream object to your friend function.
So it will be something like friend std::ostream& operator<<(std::ostream &, SoccerPlayer&);
both in prototype as well as in definition.
std::ostream operator<<(std::ostream player, SoccerPlayer& aPlayer) has to be a friend of the class or a class member to access private and protected fields.
I am trying to overload << operator , so that when i use my class object in std::cout , it prints out the data members which is supposed to get printed .
i know i have to define a friend functions signature inside of a class , and then outside of the class i define two friend functions doing the job,
but i want to hand over the class , and dont want the user to do literally anything and i want the class take care of everything .
How can i achieve such a thing in c++?
Thank you in advance
C++ is designed to allow non-member functions to do things that would require a member function in other languages. A friend function is very similar to a member function, in that it can be defined within a class scope. Also (and this can be confusing) if you declare a friend function only within a class scope, it can only be accessed by passing an object of that class to it.
struct printme {
friend std::ostream &operator<< ( std::ostream &os, printme const & )
{ return os << "hello"; }
friend void named_friend( printme const & ) {}
};
std::cout << printme(); // OK
named_friend( printme() ); // OK
void (*fn_ptr) = named_friend; /* function not found
it can only be found by association with printme */
Although this subtle rule is odd at first, it reflects the idea that nonmember functions can also be encapsulated by the class.
For more info, read up on argument-dependent lookup (ADL).
we usually uses << in the following way:
cout<<myobject;
if you make operator<<() a member function of your class you have to use the following syntax
to call operator<<()
myobject<<cout;
do you want it that way? if its ok for you , you can make it a member function .
if you want it like
cout<<myobject
- you have to make operator<<() a friend function of your class
Here is an example:
#include <iostream>
#include <string>
using namespace std;
class A {
public:
string pr() { return "Hi, I'm class A"; }
};
ostream &operator << (ostream &o, const A &a) {
o << a.pr();
return o;
}
int main() {
A a;
cout << a << endl;
return 0;
}
However, from my experience, don't do that. Oveloading is academically nice, but it makes it diffult to search your application for its implementation, and even comprehend that << has been overloaded. I always use something of the form cout << myobject.tostring()