Overloading Operator <<

J

jois.de.vivre

Hi, I'm having some trouble overloading the << operator. I have the
following, very simple code:

#include <iostream>
using namespace std;

class test
{
private:
int val;
public:
test():val(0){}
const int GetVal() const{
return val;
}

ostream& operator<< (ostream& os , test& a) {
os << a.GetVal();
return os;
}
};
//------End Sample Code

I get the following error during compile. What does this error mean?

error: 'std::eek:stream& test::eek:perator<<(std::eek:stream&, test&)' must
take exactly one argument

I want to do something like

test MyTest;
cout << test << endl;

Thanks
 
T

Thomas Tutone

jois.de.vivre said:
Hi, I'm having some trouble overloading the << operator. I have the
following, very simple code:

#include <iostream>
using namespace std;

class test
{
private:
int val;
public:
test():val(0){}
const int GetVal() const{
return val;
}

ostream& operator<< (ostream& os , test& a) {
os << a.GetVal();
return os;
}
};
//------End Sample Code

I get the following error during compile. What does this error mean?

error: 'std::eek:stream& test::eek:perator<<(std::eek:stream&, test&)' must
take exactly one argument

operator<< can either be a member function and take one argument - an
ostream& - or it can be a nonmember function and take two arguments -
an ostream& and a const test&. You conflate the two - you both make it
a member function, but you also include two arguments. Hence the error
message. Choose one or the other. And typically people make it a
nonmember function, and I suggest you do the same.

By the way, make it const test&, not test&.

Best regards,

Tom
 
I

Ian

ostream& operator<< (ostream& os , test& a) {
os << a.GetVal();
return os;
}
};
//------End Sample Code

I get the following error during compile. What does this error mean?

error: 'std::eek:stream& test::eek:perator<<(std::eek:stream&, test&)' must
take exactly one argument
It means the member operator<< must have one argument.

try

friend std::eek:stream& operator<<( std::eek:stream& os, const test& a)
{
os << a.GetVal();
return os;
}

Or if no private members are accessed, put the operator outside of the
class.

Ian
 
?

=?iso-8859-1?Q?Ali_=C7ehreli?=

Thomas Tutone said:
operator<< can either be a member function and take one argument - an
ostream& - or it can be a nonmember function and take two arguments -
an ostream& and a const test&. You conflate the two - you both make it
a member function, but you also include two arguments. Hence the error
message. Choose one or the other. And typically people make it a
nonmember function, and I suggest you do the same.

Well, OP is probably trying to use it in this usual context:

test my_test;
cout << my_test;

In that case, operator<< must be a free function and take two arguments.

Also, regarding Ian's post, if needed, the 'friend' keyword goes with the
in-class declaration of the free function; not with the definition of it:

class test
{
friend ostream & operator<< (ostream &, test const &);

/* ... */
};

ostream & operator<< (ostream & os, test const & object)
{
return os << object.val;
}

Of course, since private access is not needed in the OP's case, it is better
to just define the free function:

class test
{
/* ... */
};

ostream & operator<< (ostream & os, test const & object)
{
return os << object.GetVal();
}

Ali
 
M

Marcus Kwok

Thomas Tutone said:
operator<< can either be a member function and take one argument - an
ostream& - or it can be a nonmember function and take two arguments -
an ostream& and a const test&. You conflate the two - you both make it
a member function, but you also include two arguments. Hence the error
message. Choose one or the other. And typically people make it a
nonmember function, and I suggest you do the same.

I looked in the FAQ and did not find the answer to this question:

Why are the nonmember function versions preferred over the member
function versions?
 
V

Victor Bazarov

Marcus said:
I looked in the FAQ and did not find the answer to this question:

Why are the nonmember function versions preferred over the member
function versions?

If you are trying to output _your_ class to an ostream object using
operator << (insertion into stream), then you simply *can't* have your
overloaded operator as a member because it has to be a member of the
'ostream', and you're not allowed to modify it. You're stuck with
implementing operator<< as non-member.

Now, as to why sometimes implementing two-operand operators is better
as non-member than a member, it's covered in Effective C++ book. And
you can only consider the reasons if you have a choice. In your case
you don't.

V
 
M

Marcus Kwok

Victor Bazarov said:
If you are trying to output _your_ class to an ostream object using
operator << (insertion into stream), then you simply *can't* have your
overloaded operator as a member because it has to be a member of the
'ostream', and you're not allowed to modify it. You're stuck with
implementing operator<< as non-member.

Doesn't this contradict Thomas's first sentence above? What about the
member function

ostream& MyClass::eek:perator<<(ostream&);


Will this not allow you to do, for example,

MyClass c;
std::cout << c;


or does the declaration imply

c << std::cout;
(which is backwards from the way it's supposed to be)?
Now, as to why sometimes implementing two-operand operators is better
as non-member than a member, it's covered in Effective C++ book. And
you can only consider the reasons if you have a choice. In your case
you don't.

Thanks, I'll look into picking up that book; it seems to be very well
regarded.
 
V

Victor Bazarov

Marcus said:
Doesn't this contradict Thomas's first sentence above? What about the
member function

ostream& MyClass::eek:perator<<(ostream&);


Will this not allow you to do, for example,

MyClass c;
std::cout << c;

No. It would allow you to do this

MyClass c;
c << std::cout;
or does the declaration imply

c << std::cout;
(which is backwards from the way it's supposed to be)?

Yes. Well, it's not backwards. The left operand of a binary member is
always the object of the class in which the operand is the member. You
could, for fun, define it as

ostream& MyClass::eek:perator>>(ostream&);

and use it as

MyClass c;
c >> std::cout << std::endl;

A bit awkward, but some may find it making sense...

V
 
M

Marcus Kwok

Victor Bazarov said:
No. It would allow you to do this

MyClass c;
c << std::cout;


Yes. Well, it's not backwards. The left operand of a binary member is
always the object of the class in which the operand is the member.

OK, I understand. Thanks.
You could, for fun, define it as

ostream& MyClass::eek:perator>>(ostream&);

and use it as

MyClass c;
c >> std::cout << std::endl;

A bit awkward, but some may find it making sense...

Maybe it will be useful when they start an Obfuscated C++ contest
(IOC++CC?) :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,786
Messages
2,569,626
Members
45,328
Latest member
66Teonna9

Latest Threads

Top