How does the << Operator exactly work? - c++

I have some problems in understanding the << operator.
If I have:
#include <iostream>
using namespace std;
//...
int t = 5;
cout << "test is: " << t << endl;
Now the function operator<< is called.
ostream& operator<<(ostream& out, string* s)
{
return out << s << endl;
}
ostream& operator<<(ostream& out, int* value)
{
return out << value << endl;
}
the string-pointer points to the address with value test is: but to what does the element out refer (to cout?)? and is the function body of ostream& correct in that way?
Thank you so much for any explanation.

First, let's fix your code: the operators should be taking const references or values instead of pointers:
ostream& operator<<(ostream& out, const string& s) // const reference
ostream& operator<<(ostream& out, int i) // value
Now to your question: you are correct, the out parameter receives the reference to the cout, or whatever is the ostream& returned from the expression on the left side of <<. The expression on the left of << is not necessarily cout, though - other common cases are results of other << operators* for chaining, and stream manipulators. In all cases these expressions return a reference to ostream so that the "chain" could continue.
* The reason the operator<< return an ostream& is so that you could chain the output. In overwhelming number of cases you wold return the same ostream& that you receive as the first parameter, although there is no limitation on the part of the standard C++ library requiring you to do that.

int t = 5;
cout << "test is: " << t << endl;
First call would be to:-
ostream& operator<<(ostream& out, const char* str)
out = cout
str = "test is: "
Second call would be applied on object returned by first call which is ostream.
ostream& operator<<(ostream& out, int x)
out = cout
x = t

This is not true. It's int not int*, and char const* not string*.
out, of course, refers to std::cout in this example. What else would it be?
And no those bodies are not correct in the slightest — they attempt to reinvoke themselves infinitely, and do nothing else.

Related

Error with << operator overload returning a std::string

I'm having troubles understanding the reason why the compiler accuses error, when the return type of a << operator overload is std::string. Could you please help me understand?
Bellow is an reproducible example, which gives a gigantic error.
class XY
{
int X__;
int Y__;
public:
XY(int x, int y):X__(x), Y__(y){}
~XY(){}
std::string operator<<(const XY_cartesiano& c)
{
std::stringstream ss;
ss << "{ " << X__ << ", " << Y__ << " }";
return ss.str();
}
int x() const{return X__;}
int y() const{return Y__;}
};
void main()
{
XY a(1,2);
std::cout << a;
}
Let's take something like this as an example:
cout << "My number is " << 137 << " and I like it a lot." << endl;
This gets parsed as
((((cout << "My number is ") << 137) << " and I like it a lot.") << endl);
In particular, notice that the expression cout << "My number is " has to evaluate to something so that when we then try inserting 137 with << 137 the meaning is "take 137 and send it to cout."
Imagine if cout << "My number is " were to return a string. In that case, the << 137 bit would try to use the << operator between a string on the left-hand side and an int on the right-hand side, which isn't well-defined in C++.
The convention is to have the stream insertion operator operator << return a reference to whatever the left-hand side stream is so that these operations chain well. That way, the thing on the left-hand side of << 137 ends up being cout itself, so the above code ends up essentially being a series of chained calls to insert things into cout. The signature of these functions therefore usually look like this:
ostream& operator<< (ostream& out, const ObjectType& myObject) {
// ... do something to insert myObject into out ... //
return out;
}
Now, everything chains properly. Notice that this function is a free function, not a member function, and that the left-hand side is of type ostream and the right-hand side has the type of your class in it. This is the conventional way to do this, since if you try overloading operator << as a member function, the left-hand side will be an operand of your class type, which is backwards from how stream insertion is supposed to work. If you need to specifically access private fields of your class in the course of implementing this function, make it a friend:
class XY {
public:
...
friend ostream& operator<< (ostream& out, const XY& myXY);
};
ostream& operator<< (ostream& out, const XY &myXY) {
...
return out;
}
Correct way to overload << operator in your case is
ostream& operator<<(ostream& os, const XY& c)
{
os << c.X__ <<" "<< c.Y__ ;
return os;
}
You have overloaded operator<< in a way that's incompatible with the conventions you must follow when you intend to use the operator with a std::ostream object like std::cout.
In fact, your operator<<'s signature has nothing to do with streams at all! It is just a member function of XY which takes another XY (which it then does not use), returns a string and has an unsual name. Here's how you would theoretically call it:
XY a(1,2);
XY b(1,2);
std::string x = (a << b);
The correct way to overload operator<< for use with streams is to make the operator a non-member function, add a stream reference parameter and return a stream reference to the stream argument. You also do not need a string stream; you write directly to the stream you get:
#include <iostream>
class XY
{
int x;
int y;
public:
XY(int x, int y) : x(x), y(y) {}
int X() const { return x; }
int Y() const { return y; }
};
std::ostream& operator<<(std::ostream& os, XY const& c)
{
os << "{ " << c.X() << ", " << c.Y() << " }";
return os;
}
int main()
{
XY a(1,2);
std::cout << a;
}

How to overload the << operator

I am trying to overload the << operator by using the code
inline ostream& operator<< (ostream& out, Node& n){n.print(out); return out;}
and the print function I call is just
void Node::print(ostream& out){
out<< freq << " " << input<<" " << Left<< " " << Right<< endl;
}
Left and right are both pointers that print out in hex when I just call the print function. But when I use the << operator it just prints everything in hex i.e 0x600084d40. I don't want it printing out in Hex I want the values of freq and input when and the two hex pointers when I print it.
When I try to print it out I am printing a Node* i dont know if that has anything to do with it.
Thank you for any help.
When I try to print it out I am printing a Node* i dont know if that has anything to do with it.
It definitely does.
Node* n = ...;
std::cout << n;
invokes overload that just prints a pointer. You need to use:
Node* n = ...;
std::cout << *n;
If you want
std::cout << n;
to work similar to
std::cout << *n;
you'll have to provide an overload.
inline ostream& operator<< (ostream& out, Node* n)
{
return (out << *n);
}
Suggested Improvements
operator<< functions should use const&, not a non-const reference.
inline ostream& operator<<(ostream& out, Node const& n);
That would necessitate changing print to a const-member function.
I would also recommend changing the return type of print to std::ostream&.
std::ostream& print(std::ostream& out) const;
Now, the implementations would look like:
std::ostream& Node::print(std::ostream& out)
{
return (out<< freq << " " << input<<" " << Left<< " " << Right<< std::endl);
}
inline std::ostream& operator<<(std::ostream& out, Node const& n)
{
return n.print(out);
}
inline std::ostream& operator<<(std::ostream& out, Node const* n)
{
return (out << *n);
}
Why use the print function? Instead you could just use overloading with friend functions. Previously when implementing this I needed to pass the object by const reference like this const Node &nameand also return an ostream&
Assuming that freq and input are members of the class, your code should look like this in your .cpp:
ostream& operator<<(ostream& out, const Node& n)
{
return out<<n.freq<< " " <<n.input<<" "<<n.Left<<" "<< n.Right;
}
and this in the .h:
friend ostream& operator<<(ostream& out, const Node& n);
If this needs to take pointers you can simply modify it to be:
ostream& operator<<(ostream& out, const Node* n)
{
return out<<n->freq<< " " <<n->input<<" "<<n->Left<<" "<< n->Right;
}
and:
friend ostream& operator<<(ostream& out, const Node* n);
I hope this helps!

How to get THIS when overloading operator in C++

I'm a student learning c++. today, I was making a operator overload function to use it in 'cout'. following is a class that contains name, coordinates, etc.
class Custom {
public:
string name;
int x;
int y;
Custom(string _name, int x, int y):name(_name){
this->x = x;
this->y = y;
}
int getDis() const {
return static_cast<int>(sqrt(x*x+y*y));
}
friend ostream& operator << (ostream& os, const Custom& other);
};
ostream& operator << (ostream& os, const Custom& other){
cout << this->name << " : " << getDis() << endl;; // error
return os;
}
However, this code isn't working because of 'THIS' keyword that I was expecting it points to the object. I want to show the object's name and distance value. How can I solve it? I think it is similar with Java's toString method so that it will be able to get THIS.
Thanks in advance for your answer and sorry for poor english. If you don't understand my question don't hesitate to make a comment.
this is available only in member functions, but your operator<< is not a class member (declaring it as friend does not make it a member). It is a global function, as it should be. In a global function, just use the arguments you are passing in:
ostream& operator << (ostream& os, const Custom& other)
{
os << other.name << " : " << other.getDis() << endl;
return os;
}
Also note os replaced cout in the code above. Using cout was an error - the output operator should output to the provided stream, not to cout always.

Can operator<< in derived class call another operator<< in base class in c++?

In my code, Manager is derived from Employee and each of them have an operator<< override.
class Employee{
protected:
int salary;
int rank;
public:
int getSalary()const{return salary;}
int getRank()const{return rank;}
Employee(int s, int r):salary(s), rank(r){};
};
ostream& operator<< (ostream& out, Employee& e){
out << "Salary: " << e.getSalary() << " Rank: " << e.getRank() << endl;
return out;
}
class Manager: public Employee{
public:
Manager(int s, int r): Employee(s, r){};
};
ostream& operator<< (ostream& out, Manager& m){
out << "Manager: ";
cout << (Employee)m << endl; //can not compile, how to call function of Employee?
return out;
}
I hoped cout << (Employee)m << endl; would call ostream& operator<< (ostream& out, Employee& e), but it failed.
Cast to a reference instead of a copy:
cout << (Employee&)m << endl; //can not compile, how to call function of Employee?
Also note the ostream operator is in no way member of the class(it seems you are confused about that from the title of the question).
Change cout << (Employee)m << endl; to cout << (Employee&)m << endl;.
The explanation of the error message is this:
When you attempt the cast (Employee)m, you are creating a temporary. The operator<< overload takes a reference. You cannot take a reference to a temporary.
Since you really just want it to print it's own data (not make a copy of itself), you cast the reference you have to the reference of the type you need (it's base class).
As jrok pointed out in his answer, you can also accomplish this by providing a virtual function to print the data. That would be a simpler approach as it would not require you to overload operator<< for every derived class.
The usual way of doing this is to have (a possibly private or protected) virtual print (or any other suitable name) function in the base class that derived classes can override.
You only provide general operator<< for a reference to the base class and call print inside it. The overriding print functions can call the base's print, if need be.
Your overload:
ostream& operator<< (ostream& out, Employee& e)
only works for references to Employee objects, so it won't work on non-reference values (like the result of a cast).
Normally, the prototype would be:
ostream& operator<< (ostream& out, const Employee& e)
which also provides the reassurance that printing an Employee doesn't mutate it. If you change that, things should work just fine. (ostream& does have to be a reference, not a const reference, because the ostream is mutated by the print operation.)
There are two problems which combined make your compilation to fail.
(1) This declaration and definition:
ostream& operator<< (ostream& out, Employee& e){
out << "Salary: " << e.getSalary() << " Rank: " << e.getRank() << endl;
return out;
}
Despite you don't change e, you take it reference to non-const. This forbids you calling this operator on an rvalue.
(2) This line
cout << (Employee)m << endl;
As said by others you are slicing m. In addition, the cast (Employee) m returns a temporary Employee which is an rvalue.
In summary, the cast (Employee)m yields an rvalue which cannot bind to e.
You can fix either one or the other to make your code compiler but it's better to fix both problems to make your code more robust:
// ...
ostream& operator<< (ostream& out, const Employee& e) {
// ...
// ...
cout << static_cast<Employee&>(m) << endl;
// ...
First, you overload a global function. This is another concept than overriding. see Override and overload in C++
Next, your cast is wrong. This should do:
ostream& operator<< (ostream& out, Manager& m){
out << "Manager: ";
cout << static_cast<Employee&>(m) << endl; //can not compile, [...]?
return out;
}
...if you really want to overload the global << operator.

Overloading I/O operator C++

I'm trying to overload the << operator. I'm expecting the output to be InitializingHello WorldOut but it is just outputting Hello World. I can't figure out what is wrong with my code. Thanks for your help.
#include <iostream>
using namespace std;
ostream &operator << (ostream &out, const char* &s)
{
out << "Initializing" << s << "Out";
return out;
}
void main() {
cout << "Hello World" << endl;
system("Pause");
}
"Hello World" is actually of type const char[12], which can decay into an r-value (temporary) of type const char *, but your function takes a reference to a const char*, and as you may know, you cannot bind a reference to a non-const r-value. So your operator is not called, but instead the standard ostream &operator << (ostream &out, const char* s) is.
PS. Please do not write void main(). It should be int main() unless you are in an embedded system (not likely).
There already is an overload for << with the exact same prototype. The compiler cannot decide which to use...
There is already a operator<< for const char* defined in the standard library, which is used in the output. Your overload is not used because the temporary string literal cannot be bound to the non-const reference in the operators second parameter.
If you remove the reference or make it const, then your operator is called. It doesn't even conflict with the one in your standard library, since that one is implemented as a function template. Yours is not, and non-templated functions are preferred by the compiler.
If it is then called, it leads to a stack overflow because out << "Initializing" immediately calls the same operator again recursively.
rodrigo pointed out that the type of a string literal is const char[x], and I had an evil idea:
#include <iostream>
using namespace std;
template<int len>
ostream &operator << (ostream &out, const char (&s)[len])
{
out << ((const char*)"Initializing") << ((const char*)s) << ((const char*)"Out");
return out;
}
int main() {
cout << "Hello World" << endl;
}
http://ideone.com/7wCNy
I think that since the left hand side is in the std namespace, it's using the function ostream& std::operator << (ostream &out, const char* s) that's defined in the std namespace instead of yours in the global namespace. If you were to try to put yours into the std namespace, you'd get a linker error. Your only real hope is to change the types of one side or the other, probably by making a wrapper around them.
struct charptr {
const char* ptr;
charptr(const char* p) :ptr(p) {}
};
ostream &operator << (ostream &out, const charptr &s)
{
out << "Initializing" << s.ptr << "Out";
return out;
}
int main() { //int main, not void
cout << charptr("Hello World") << endl;
system("Pause");
}