I tried to write an simple example for the <<-operator-overloading.
Before, i've never used the keyword "friend". But it does not work without it. What is the mistake i did or why do i need the friend keyword here?
class rational{
public:
rational(double num, double count)
: n(num),c(count){}
rational& operator+=(const rational& b){
this->n+= b.n;
this->c+= b.c;
return *this;
}
friend std::ostream& operator<<(std::ostream& os, const rational& obj)
{
std::cout << obj.n << "," << obj.c << std::endl;
return os;
}
private:
double n;
double c;
};
Thanks
You didn't make any mistake. The friend keyword gives your operator<<() implementation access to private (and protected, if you had any) members of your class.
Note that because it's a friend, operator<<() here is implicitly a free function and not a member function (if it were a member function, it could access private things already!). Because it's declared and defined only inside the class, it can only be found by argument-dependent lookup, but this is fine for operator<< and is a detail you don't have to worry about yet.
You want to stream objects whose internals are not accessible through their class' public interface, so the operator can't get at them. Then you have two choices: Either put a public member into the class which does the streaming
class T {
public:
void stream_to(std::ostream& os) const {os << obj.data_;}
private:
int data_;
};
and call that from the operator:
inline std::ostream& operator<<(std::ostream& os, const T& obj)
{
obj.stream_to(os);
return os;
}
or make the operator a friend
class T {
public:
friend std::ostream& operator<<(std::ostream&, const T&);
private:
int data_;
};
so that it can access the class' private parts:
inline std::ostream& operator<<(std::ostream& os, const T& obj)
{
os << obj.data_;
return os;
}
You are declaring and defining the operator inside the class, thus without friend it has an implicit first operand of type rational. You wouldn't have such problem if you had declared the operator outside the class, but then you wouldn't have access to n and c.
Related
I've found myself in a bit of trouble trying to overload operator<< correctly. I've searched around other questions about it, but none of the answers seemed to fit this one, so here it is:
I have a class (Register) that stores specimens of another class(subclasses of Film, which is abstract). The overloaded operator << for Register should put all the data stored in each Film type element on screen through the ostream class.Here's the code:
class Register{
private:
int elementNum;
Film* pData;
};
ostream &operator<<(ostream & os,const Register &v);
These are in the header, operator << in the cpp:
ostream &operator<<(ostream & os,const Register &v){
for(int i=0;i<v.elementNum;i++){
os<<v.pData[i].print()<<endl;
}
return os;
}
Problem is, this way i cannot access the private variables of Register. So I tried putting the overaloaded operator<< as a member of Register, but then the compiler tells me the function must take only one argument. Last, if I remove ostream& os from the parameters, it tells me the function needs two arguments. So i would be interested in a solution where the information stored in pData can be put on screen efficiently with operator <<. Thanks in advance!
You have to declare operator<< as a friend if access to Register implementation (private data) has to be granted:
class Register{
private:
//...
friend std::ostream &operator<<( std::ostream & os,const Register &v);
};
std::ostream &operator<<( std::ostream & os,const Register &v) {
for( int i=0; i<v.elementNum; i++){
os << v.pData[i].print() << std::endl;
}
return os;
}
Friend function has access to all private ( as well as protected and public) data of a class that declared a friend.
C++ Standard n3337 § 11.3/1 says
Friends
A friend of a class is a function or class that is given permission to
use the private and protected member names from the class. A class
specifies its friends, if any, by way of friend declarations. Such
declarations give special access rights to the friends, but they do
not make the nominated friends members of the befriending class.
§ 11.3/2
Declaring a class to be a friend implies that the names of private and
protected members from the class granting friendship can be accessed
in the base-specifiers and member declarations of the befriended
class.
Make your operator<< a friend of the class. You can read it up here.
You could make operator<< a friend of class Register see code below:
class Register{
private:
friend ostream &operator<<(ostream & os,const Register &v);
int elementNum;
Film* pData;
};
Thus, operator<< will have access to class Register private members.
To access the private members of Register, make operator<< a friend function:
class Register{
private:
int elementNum;
Film* pData;
friend ostream &operator<<(ostream & os,const Register &v);
};
I implemented the OS-Operator in a project like this:
XYZ.h file
friend std::ostream& operator<<(std::ostream& os, const Liwanze& arg);
XYZ.cpp file
std::ostream& operator<<(std::ostream& os, const Liwanze& arg) {
string area = "";
if (arg.loc == 1)
area = "Buxtehude";
if (arg.loc == 2)
area = "Bangladesch";
if (arg.loc == 3)
area = "Zimbabwe";
if (arg.loc == 4)
area = "Bronx";
os << arg.name << " [" << area << "] ";
return os;
}
or if you wish to avoid polluting your class with unwanted friends, defer the formatting to a public member of Register.
class Register{
public:
void writeTo(std::ostream& os) const {
for( int i=0; i<elementNum; i++){
os << pData[i].print() << std::endl;
}
}
private:
//...
};
std::ostream &operator<<( std::ostream & os,const Register &v) {
v.writeTo(os);
return os;
}
If you make the writeTo function defer to a protected virtual function, then operator<< will work on anything derived from Register, even in a multi-threaded environment.
class Register{
public:
// public non-polymorphic interface...
void writeTo(std::ostream& os) const {
os << "any header information\n" << endl;
std::lock_guard<std::mutex> myLock(_myInternalMutex); // in MT environment
handleWriteTo(os); // defer to protected polymorphic implementation
}
protected:
virtual void handleWriteTo(std::ostream& os) const {
for( int i=0; i<elementNum; i++){
os << pData[i].print() << std::endl;
}
}
private:
//...
};
std::ostream &operator<<( std::ostream & os,const Register &v) {
v.writeTo(os);
return os;
}
I have a class Counter and I want to overload operator << to output the data member of Counter. I tried to make the ostream overloading a member function:
Counter{
public:
std::ostream& operator<<(std::ostream& outStream, const Counter& c);
private:
int count_;
};
std::ostream& Counter::operator<<(std::ostream& outStream, const Counter& c){
outStream << c.count_;
return outStream;
}
But the g++ compiler always outputs the same error:
‘std::ostream& Counter::operator<<(std::ostream&, const Counter&)’ must take exactly one argument
However, if I changed the overloading function to be a friend of the class, it worked all well, like this:
Counter{
public:
friend std::ostream& operator<<(std::ostream& outStream, const Counter& c);
private:
int count_;
};
std::ostream& operator<<(std::ostream& outStream, const Counter& c){
outStream << c.count_;
return outStream;
}
Does this mean that the the stream operator overloading cannot be a member function of a class?
Add a public query method that returns the value of count_, then it does not have to be a friend:
Counter{
public:
int count() const { return count_; }
private:
int count_;
};
std::ostream& operator<<(std::ostream& outStream, const Counter& c){
outStream << c.count();
return outStream;
}
If you put the ostream operator in the class itself then it will not work the way you expect it to. It would be a member function meaning to invoke it one would have to do this: c.operator<<("output") which is obviously not what you mean to do. For it to work as you expect an ostream operator it must be outside the class. You can do this by making it a friend or just put it outside of the class and use getters (accessors) to output the data.
It doesn't have to be a friend, but it can't be a member. Member operators only work when they are inside the class which corresponds to the left-hand operand.
Unfortunately the useful overloads for the streaming output operators ( << ) cannot be class members, because the ostream& must be on the left in use and declaration. They do not need to be friends of the class you wish to stream unless they need access to protected or private members. This means that if you can implement a streaming operator using just public functions such as observers/accessors without declaring it a friend.
In your first Counter class you are declaring a member function of the class that does not seem valid. In the second example of the Counter class you are stating that your operator overload for << , which seems valid, has access to the private members. In the second example the function must still be declared outside the class.
Wikipedia Operators in C and C++ has a good list of possible operator overloads, including the in class << overloads even though they are not very useful. The in class overloads must be called backwards CounterInstance << cout; which is counterintuitive.
Code snippet from lexical_cast:
class lexical_castable {
public:
lexical_castable() {};
lexical_castable(const std::string s) : s_(s) {};
friend std::ostream operator<<
(std::ostream& o, const lexical_castable& le);
friend std::istream operator>>
(std::istream& i, lexical_castable& le);
private:
virtual void print_(std::ostream& o) const {
o << s_ <<"\n";
}
virtual void read_(std::istream& i) const {
i >> s_;
}
std::string s_;
};
std::ostream operator<<(std::ostream& o,
const lexical_castable& le) {
le.print_(o);
return o;
}
std::istream operator>>(std::istream& i, lexical_castable& le) {
le.read_(i);
return i;
}
Based on document,
template<typename Target, typename Source>
Target lexical_cast(const Source& arg);
1> Returns the result of streaming arg into a standard library
string-based stream and then out as a Target object.
2> Source is OutputStreamable
3> Target is InputStreamable
Question1> For User Defined Type (UDT), should the OutputStreamable or InputStreamable always have to deal with std::string? For example, given a class containing a simple integer as member variable, when we define the operator<< and operator>>, what is the implementation code looks like? Do I have to convert the integer as a string? Based on my understanding, it seems that UDT always has to deal with std::string in order to work with boost::lexical_cast and boost::lexcial_cast needs the intermediate std::string to do the real conversion jobs.
Question2> Why the return value of operator<< or operator>> in above code is not reference to std::ostream& or std::istream& respectively?
To make your class usable with lexical_cast, just define the "stream" operators for it.
From Boost.LexicalCast Synopsis:
Source is OutputStreamable, meaning that an operator<< is defined that takes a std::ostream or std::wostream object on the left hand side and an instance of the argument type on the right.
Target is InputStreamable, meaning that an operator>> is defined that takes a std::istream or std::wistream object on the left hand side and an instance of the result type on the right.
Target is CopyConstructible [20.1.3].
Target is DefaultConstructible, meaning that it is possible to default-initialize an object of that type [8.5, 20.1.4].
:
// either inline friend, out-of-class friend, or just normal free function
// depending on whether it needs to access internel members
// or can cope with the public interface
// (use only one version)
class MyClass{
int _i;
public:
// inline version
friend std::ostream& operator<<(std::ostream& os, MyClass const& ms){
return os << ms._i;
}
// or out-of-class friend (friend declaration inside class only)
friend std::ostream& operator<<(std::ostream& os, MyClass const& ms);
// for the free function version
int get_i() const{ return _i; }
};
// out-of-class continued
std::ostream& operator<<(std::ostream& os, MyClass const& ms){
return os << ms._i;
}
// free function, non-friend
std::ostream& operator<<(std::ostream& os, MyClass const& ms){
return os << ms.get_i();
}
The same of course for operator>>.
Anyone got an idea on how to write an operator for a class that isn't a member function of the class?
Just make it a free function, or a friend function. A good example of this is operator<<:
class X {
public:
int x;
}
ostream& operator<< (ostream& os, const X& x) {
os << x.x;
return os;
}
The benefit of making it a friend function is that you have direct access to private members, whereas a free function must access all members via public methods.
Arithmetic operators, stream operators, et cetera are often not members of a class. However, they may need to be friends in order to access private data members.
I prefer not to use friend and to expose methods that can be used by the operators instead. I believe this to be more in keeping with the Open/closed principle, as I could easily add a subtraction operator without editing the class.
These are handy for unit-testing, too (I can "inject" a std::ostringstream to test the output of print(), for instance).
Here is an example:
#include <iostream>
class Number
{
public:
Number(int j)
:i(j)
{
}
void print(std::ostream& os) const
{
os << i;
}
int value() const
{
return i;
}
private:
int i;
};
std::ostream& operator <<(std::ostream& os, const Number& n)
{
n.print(os);
return os;
}
Number operator +(const Number& n, const Number& o)
{
return Number(n.value() + o.value());
}
int main()
{
Number a(4), b(5), c(a + b);
std::cerr << c << std::endl;
}
Just declare the global function with the operator name:
Point operator+(Point& p, Vector& v) {
return new Point(p.x + q.i, p.y + q.j);
}
Basically, you can take the operator out of the class, and add a parameter to the beginning of the parameter list. In many cases, you will also need to declare the operator function as a friend.
For instance
class Foo
{
Foo operator +( Foo const& other );
};
becomes
class Foo
{
friend Foo operator +( Foo const&, Foo const& );
};
Foo operator +( Foo const& first, Foo const& second );
The friend statement allows the operator to still access any private or protected members needed.
Note that there are some restrictions on which operators can be overloaded in this manner. See this article for such a list.
I'm trying to overload the << operator for the nested class ArticleIterator.
// ...
class ArticleContainer {
public:
class ArticleIterator {
// ...
friend ostream& operator<<(ostream& out, const ArticleIterator& artit);
};
// ...
};
If I define operator<< like I usually do, I get a compiler error.
friend ostream& operator<<(ostream& out, const ArticleContainer::ArticleIterator& artit) {
The error is 'friend' used outside of class. How do I fix this?
You don't put the friend keyword when defining the function, only when declaring it.
struct A
{
struct B
{
friend std::ostream& operator<<(std::ostream& os, const B& b);
};
};
std::ostream& operator<<(std::ostream& os, const A::B& b)
{
return os << "b";
}
You must declare it as a friend inside the class, then define it outside the class without the friend keyword.
class ArticleContainer {
public:
class ArticleIterator {
// ...
friend ostream& operator<<(ostream& out, const ArticleIterator& artit);
};
};
// No 'friend' keyword
ostream& operator<<(ostream& out, const ArticleIterator& artit);
the friend keyword is used in the declaration to specify that this func/class is a friend. In the definition outside the class you may not use that keyword. Just remove it