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.
Related
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.
I am trying to overload operator '=' and operator '<<' by the same method.
class Vect{
public:
//..
Vect& operator=(const Vect& a);
ostream& operator<<(ostream& out, const Vect& vect);
//..
private:
int *data;
int size;
};
this work
Vect& Vect:: operator=(const Vect& a){
//..
//copy data operator
for(int i = 0; i< size; i++){
data[i] = a.data[i];
}
return *this;
}
however: this code cause error
[Error] 'std::ostream& Vect::operator<<(std::ostream&, const Vect&)' must take exactly one argument
ostream& Vect::operator<<(ostream& out, const Vect& vect){
//.. print vect
}
I am reading "Data structure and algorithms in C++" book part (1.5.4).
They said i have to use class friends for overloading '<<' operator because it is access private members data.
I don't understand why. Overloading '=' operator i also access private member data without using "friend".
When you put a function declaration inside the class definition, it becomes by default a member function, so...
class Vect {
public:
ostream& operator<<(ostream& out, const Vect& vect);
};
...won't compile as it requests creation of a << function that takes too many arguments arguments: any member function operator<< is expected to use *this as the "left hand side" argument, and take one other argument to be the "right hand side".
You have two options:
Replace the above with friend ostream& operator<<(ostream& out, const Vect& vect);, which tells the compiler that the function is a friend of the surrounding class, but not a member thereof. As a non-member, the two arguments it operates on are out and vect - there is no *this object involved. That all works fine, and being a friend the definition also has access to private and protected member data in vect.
Move the operator<< declaration outside the class Vect definition; that also makes it a non-member function, but that doesn't make it a friend.
Overloading '=' operator i also access private member data without using "friend"
operator= is declared as a member function, which can access the private member.
They said i have to use class friends for overloading '<<' operator because it is access private members data. I don't understand why.
The problem is you're declaring operator<< as a member function, which should be declared as a non-member function. That's why you got the error.
operator<< should be a non-member function, because it needs a different type as its left-hand argument, i.e. std::ostream&, instead of Vect& when declared as a member function.
That means, as a non-member function, operator<< couldn't access the private member of the class unless you declare it as friend, such as:
class Vect {
public:
//..
friend ostream& operator<<(ostream& out, const Vect& vect);
//..
Note the above syntax makes operator<< a non-member function now.
I have the following class template which will accept both primitives and object. However like this I can only print primitives. How can I make it function using both primitives and objects? Thanks
template<class T>
class A
{
private:
vector <T> l;
public:
void print() const
{
for (int i=0;i<.size();i++)
{
cout<<l[i]<<endl; //error here
}
}
};
The reason why you can print primitives is that <iostream> provides overloads for operator<< for them.
To let your template print your classes in the same way, you need to define your own implementation of the operator:
// This implementation puts operator << outside your class.
// Mark it "friend" in MyClass if it needs access to private members of MyClass.
ostream& operator<<(ostream& ostr, const MyClass& myClass) {
// Do the printing based on the members of your class
ostr << myClass.member1 << ":" << myClass.member2;
return ostr;
}
The compiler will detect this operator during template expansion, and use it for printing when you do this:
cout<<l[i]<<endl;
You can put operator<< inside your class as well:
ostream &operator<<(ostream &os) {
ostr << member1 << ":" << member2;
}
I am assuming that here, you want to print an object instead of a variable belonging to a fundamental datatype.
For such cases, you can look at operator overloading in C++(more specifically overloading insertion operator).
For more information about overloading the insertion operator for an object, you can visit this URL
http://msdn.microsoft.com/en-us/library/1z2f6c2k.aspx
Given below is an example about how to go about it
ostream& operator<<(ostream& os, const Datatype& dt)
{
os << dt.a <<" " << dt.b;
return os;
}
Here Datatype is the name of the class and a and b are two private members of a and b which will be printed when you try to print the object.
However, to overload using this technique, do not forget to make this function as a friend function of the class(as given below) as the function requires access the to private members of the class.
friend ostream& operator<<(ostream& os, const Datatype& dt);
In a project I'm working on, I have a Score class, defined below in score.h. I am trying to overload it so, when a << operation is performed on it, _points + " " + _name is printed.
Here's what I tried to do:
ostream & Score::operator<< (ostream & os, Score right)
{
os << right.getPoints() << " " << right.scoreGetName();
return os;
}
Here are the errors returned:
score.h(30) : error C2804: binary 'operator <<' has too many parameters
(This error appears 4 times, actually)
I managed to get it working by declaring the overload as a friend function:
friend ostream & operator<< (ostream & os, Score right);
And removing the Score:: from the function declaration in score.cpp (effectively not declaring it as a member).
Why does this work, yet the former piece of code doesn't?
Thanks for your time!
EDIT
I deleted all mentions to the overload on the header file... yet I get the following (and only) error. binary '<<' : no operator found which takes a right-hand operand of type 'Score' (or there is no acceptable conversion)
How come my test, in main(), can't find the appropriate overload? (it's not the includes, I checked)
Below is the full score.h
#ifndef SCORE_H_
#define SCORE_H_
#include <string>
#include <iostream>
#include <iostream>
using std::string;
using std::ostream;
class Score
{
public:
Score(string name);
Score();
virtual ~Score();
void addPoints(int n);
string scoreGetName() const;
int getPoints() const;
void scoreSetName(string name);
bool operator>(const Score right) const;
private:
string _name;
int _points;
};
#endif
Note: You might want to look at the operator overloading FAQ.
Binary operators can either be members of their left-hand argument's class or free functions. (Some operators, like assignment, must be members.) Since the stream operators' left-hand argument is a stream, stream operators either have to be members of the stream class or free functions. The canonical way to implement operator<< for any type is this:
std::ostream& operator<<(std::ostream& os, const T& obj)
{
// stream obj's data into os
return os;
}
Note that it is not a member function. Also note that it takes the object to stream per const reference. That's because you don't want to copy the object in order to stream it and you don't want the streaming to alter it either.
Sometimes 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&) 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;
}
Let's say you wanted to write an operator overload for + so you could add two Score objects to each other, and another so you could add an int to a Score, and a third so you could add a Score to an int. The ones where a Score is the first parameter can be member functions of Score. But the one where an int is the first parameter can't become member functions of int, right? To help you with that, you're allowed to write them as free functions. That is what is happening with this << operator, you can't add a member function to ostream so you write a free function. That's what it means when you take away the Score:: part.
Now why does it have to be a friend? It doesn't. You're only calling public methods (getPoints and scoreGetName). You see lots of friend operators because they like to talk directly to the private variables. It's ok by me to do that, because they are written and maintained by the person maintaing the class. Just don't get the friend part muddled up with the member-function-vs-free-function part.
You're getting compilation errors when operator<< is a member function in the example because you're creating an operator<< that takes a Score as the first parameter (the object the method's being called on), and then giving it an extra parameter at the end.
When you're calling a binary operator that's declared as a member function, the left side of the expression is the object the method's being called on. e.g. a + b might works like this:
A a;
B b
a.operator+(b)
It's typically preferable to use non-member binary operators (and in some cases -- e.g. operator<<for ostream is the only way to do it. In that case, a + b might work like this:
A a;
B b
operator+(a, b);
Here's a full example showing both ways of doing it; main() will output '55' three times:
#include <iostream>
struct B
{
B(int b) : value(b) {}
int value;
};
struct A
{
A(int a) : value(a) {}
int value;
int operator+(const B& b)
{
return this->value + b.value;
}
};
int operator+(const A& a, const B& b)
{
return a.value + b.value;
}
int main(int argc, char** argv)
{
A a(22);
B b(33);
std::cout << a + b << std::endl;
std::cout << operator+(a, b) << std::endl;
std::cout << a.operator+(b) << std::endl;
return 0;
}
Im really unsure how to call the function:
friend ostream& operator<<(ostream& out, stack::myItem& theItem);
that is public to my stack object:
class stack
{
public:
stack(int capacity);
~stack(void);
void method1();
...
private:
struct myItem
{
int item;
};
...
public:
friend ostream& operator<<(ostream& out, stack& s);
friend ostream& operator<<(ostream& out, stack::myItem& theItem);
};
It's no different than using stream operator << for any other type (it is called operator overloading for a reason).
However, outputting should not modify an object, hence you really should pass it by const reference (otherwise calls with temporaries would fail to compile).
friend ostream& operator<<(ostream& out, const stack& s);
friend ostream& operator<<(ostream& out, const stack::myItem& theItem);
This operator is a classic binary operator.
// Say I have an operator declared like this:
return_type operator#(left_type lhs, right_type rhs);
// Then the invocation is done this way:
left_type L;
right_type R;
return_type result = L # R;
In the case of the streaming operator, it is a bit special since the left hand argument and the return type actually have the same type (and indeed, will refer to the same object, albeit at different times). This has been done to allow chaining.
// Chaining
std::cout << "<Output> " << 1 << std::endl;
// Which can be analyzed like such
operator<<(
operator<<(
operator<<(
std::cout ,
"<Output> "
),
1
),
std::endl
);
As you can see, the syntax merely allows a convenient invocation. One might note that the order is very well defined, it is a strict left to right evaluation.
So with your object, it would become:
stack s;
std::cout << s << std::endl;
Just like that!
Call it from where? As it's coded only the class knows about the private struct. No code external to the class could use that method since it couldn't create an instance of the struct. Marking it as friend doesn't do you much good.